Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
J
jumpserver
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ops
jumpserver
Commits
2ecfecb0
Commit
2ecfecb0
authored
Jul 25, 2018
by
ibuler
Browse files
Options
Browse Files
Download
Plain Diff
[Update] Merge with dev
parents
2abb9efe
e41add61
Hide whitespace changes
Inline
Side-by-side
Showing
33 changed files
with
467 additions
and
184 deletions
+467
-184
README.md
README.md
+5
-5
__init__.py
apps/__init__.py
+1
-1
asset.py
apps/assets/models/asset.py
+1
-1
system_user.py
apps/assets/serializers/system_user.py
+1
-1
gateway_create_update.html
apps/assets/templates/assets/gateway_create_update.html
+12
-3
system_user_detail.html
apps/assets/templates/assets/system_user_detail.html
+8
-9
views_urls.py
apps/assets/urls/views_urls.py
+0
-1
mixins.py
apps/common/mixins.py
+4
-1
django.mo
apps/i18n/zh/LC_MESSAGES/django.mo
+0
-0
django.po
apps/i18n/zh/LC_MESSAGES/django.po
+103
-81
settings.py
apps/jumpserver/settings.py
+1
-0
views.py
apps/jumpserver/views.py
+2
-2
models.py
apps/orgs/models.py
+4
-2
api.py
apps/perms/api.py
+3
-8
views_urls.py
apps/perms/urls/views_urls.py
+7
-9
_footer.html
apps/templates/_footer.html
+1
-1
api.py
apps/terminal/api.py
+2
-0
command_list.html
apps/terminal/templates/terminal/command_list.html
+39
-14
command_report.html
apps/terminal/templates/terminal/command_report.html
+104
-0
views_urls.py
apps/terminal/urls/views_urls.py
+1
-0
command.py
apps/terminal/views/command.py
+43
-5
api.py
apps/users/api.py
+21
-3
user_detail.html
apps/users/templates/users/user_detail.html
+44
-2
user_list.html
apps/users/templates/users/user_list.html
+1
-1
api_urls.py
apps/users/urls/api_urls.py
+2
-0
views_urls.py
apps/users/urls/views_urls.py
+20
-20
utils.py
apps/users/utils.py
+20
-5
login.py
apps/users/views/login.py
+5
-3
user.py
apps/users/views/user.py
+8
-2
step_by_step.rst
docs/step_by_step.rst
+1
-1
jms
jms
+1
-1
requirements.txt
requirements/requirements.txt
+1
-1
make_migrations.sh
utils/make_migrations.sh
+1
-1
No files found.
README.md
View file @
2ecfecb0
...
@@ -19,25 +19,25 @@ Jumpserver采纳分布式架构,支持多机房跨区域部署,中心节点
...
@@ -19,25 +19,25 @@ Jumpserver采纳分布式架构,支持多机房跨区域部署,中心节点
----
----
### 功能
### 功能
!
[
Jumpserver功能
](
https://jumpserver-release.oss-cn-hangzhou.aliyuncs.com/Jumpserver13.jpg
"Jumpserver功能"
)
!
[
Jumpserver功能
](
https://jumpserver-release.oss-cn-hangzhou.aliyuncs.com/Jumpserver13.jpg
"Jumpserver功能"
)
### 开始使用
### 开始使用
快速开始文档
[
Docker安装
](
http://docs.jumpserver.org/zh/
latest/quickstart
.html
)
快速开始文档
[
Docker安装
](
http://docs.jumpserver.org/zh/
docs/dockerinstall
.html
)
一步一步安装文档
[
详细部署
](
http://docs.jumpserver.org/zh/
latest
/step_by_step.html
)
一步一步安装文档
[
详细部署
](
http://docs.jumpserver.org/zh/
docs
/step_by_step.html
)
也可以查看我们完整文档包括了使用和开发
[
文档
](
http://docs.jumpserver.org
)
也可以查看我们完整文档包括了使用和开发
[
文档
](
http://docs.jumpserver.org
)
### Demo 和 截图
### Demo 和 截图
我们提供了DEMO和截图可以让你快速了解Jumpserver
我们提供了DEMO和截图可以让你快速了解Jumpserver
[
DEMO
](
http://demo.jumpserver.org
)
[
DEMO
](
http://demo.jumpserver.org
)
[
截图
](
http://docs.jumpserver.org/zh/docs/snapshot.html
)
[
截图
](
http://docs.jumpserver.org/zh/docs/snapshot.html
)
### SDK
### SDK
我们还编写了一些SDK,供你其它系统快速和Jumpserver APi交互,
我们还编写了一些SDK,供你其它系统快速和Jumpserver APi交互,
...
...
apps/__init__.py
View file @
2ecfecb0
...
@@ -2,4 +2,4 @@
...
@@ -2,4 +2,4 @@
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
#
#
__version__
=
"1.3.
2
"
__version__
=
"1.3.
3
"
apps/assets/models/asset.py
View file @
2ecfecb0
...
@@ -142,7 +142,7 @@ class Asset(OrgModelMixin):
...
@@ -142,7 +142,7 @@ class Asset(OrgModelMixin):
return
False
,
warning
return
False
,
warning
def
is_unixlike
(
self
):
def
is_unixlike
(
self
):
if
self
.
platform
not
in
(
"Windows"
,):
if
self
.
platform
not
in
(
"Windows"
,
"Windows2016"
):
return
True
return
True
else
:
else
:
return
False
return
False
...
...
apps/assets/serializers/system_user.py
View file @
2ecfecb0
...
@@ -53,7 +53,7 @@ class SystemUserAuthSerializer(AuthSerializer):
...
@@ -53,7 +53,7 @@ class SystemUserAuthSerializer(AuthSerializer):
model
=
SystemUser
model
=
SystemUser
fields
=
[
fields
=
[
"id"
,
"name"
,
"username"
,
"protocol"
,
"id"
,
"name"
,
"username"
,
"protocol"
,
"password"
,
"private_key"
,
"
login_mode"
,
"
password"
,
"private_key"
,
]
]
...
...
apps/assets/templates/assets/gateway_create_update.html
View file @
2ecfecb0
...
@@ -42,7 +42,7 @@
...
@@ -42,7 +42,7 @@
{% bootstrap_field form.domain layout="horizontal" %}
{% bootstrap_field form.domain layout="horizontal" %}
{% block auth %}
{% block auth %}
<h3>
{% trans 'Auth' %}
</h3>
<h3
id=
"auth_title"
>
{% trans 'Auth' %}
</h3>
<div
class=
"auth-fields"
>
<div
class=
"auth-fields"
>
{% bootstrap_field form.username layout="horizontal" %}
{% bootstrap_field form.username layout="horizontal" %}
{% bootstrap_field form.password layout="horizontal" %}
{% bootstrap_field form.password layout="horizontal" %}
...
@@ -72,14 +72,23 @@
...
@@ -72,14 +72,23 @@
var
protocol_id
=
'#'
+
'{{ form.protocol.id_for_label }}'
;
var
protocol_id
=
'#'
+
'{{ form.protocol.id_for_label }}'
;
var
private_key_id
=
'#'
+
'{{ form.private_key_file.id_for_label }}'
;
var
private_key_id
=
'#'
+
'{{ form.private_key_file.id_for_label }}'
;
var
port
=
'#'
+
'{{ form.port.id_for_label }}'
;
var
port
=
'#'
+
'{{ form.port.id_for_label }}'
;
var
username
=
'#'
+
'{{ form.username.id_for_label }}'
;
var
password
=
'#'
+
'{{ form.password.id_for_label }}'
;
var
auth_title
=
'#auth_title'
;
function
protocolChange
()
{
function
protocolChange
()
{
if
(
$
(
protocol_id
+
" option:selected"
).
text
()
===
'rdp'
)
{
if
(
$
(
protocol_id
+
" option:selected"
).
text
()
===
'rdp'
)
{
{
#
$
(
port
).
val
(
3389
);
#
}
{
#
$
(
port
).
val
(
3389
);
#
}
$
(
private_key_id
).
closest
(
'.form-group'
).
addClass
(
'hidden'
)
$
(
private_key_id
).
closest
(
'.form-group'
).
addClass
(
'hidden'
);
$
(
username
).
closest
(
'.form-group'
).
addClass
(
'hidden'
);
$
(
password
).
closest
(
'.form-group'
).
addClass
(
'hidden'
);
$
(
auth_title
).
addClass
(
'hidden'
);
}
else
{
}
else
{
{
#
$
(
port
).
val
(
22
);
#
}
{
#
$
(
port
).
val
(
22
);
#
}
$
(
private_key_id
).
closest
(
'.form-group'
).
removeClass
(
'hidden'
)
$
(
private_key_id
).
closest
(
'.form-group'
).
removeClass
(
'hidden'
);
$
(
username
).
closest
(
'.form-group'
).
removeClass
(
'hidden'
);
$
(
password
).
closest
(
'.form-group'
).
removeClass
(
'hidden'
);
$
(
auth_title
).
removeClass
(
'hidden'
);
}
}
}
}
...
...
apps/assets/templates/assets/system_user_detail.html
View file @
2ecfecb0
...
@@ -152,15 +152,14 @@
...
@@ -152,15 +152,14 @@
</span>
</span>
</td>
</td>
</tr>
</tr>
{#
<tr>
#}
<tr>
{#
<td
width=
"50%"
>
{% trans 'Clear auth' %}:
</td>
#}
<td
width=
"50%"
>
{% trans 'Clear auth' %}:
</td>
{#
<td>
#}
<td>
{#
<span
style=
"float: right"
>
#}
<span
style=
"float: right"
>
{#
<button
type=
"button"
class=
"btn btn-primary btn-xs btn-clear-auth"
style=
"width: 54px"
>
{% trans 'Clear' %}
</button>
#}
<button
type=
"button"
class=
"btn btn-primary btn-xs btn-clear-auth"
style=
"width: 54px"
>
{% trans 'Clear' %}
</button>
{#
</span>
#}
</span>
{#
</td>
#}
</td>
{#
</tr>
#}
</tr>
{#
<tr>
#}
{#
<tr>
#}
{#
<td
width=
"50%"
>
{% trans 'Change auth period' %}:
</td>
#}
{#
<td
width=
"50%"
>
{% trans 'Change auth period' %}:
</td>
#}
...
...
apps/assets/urls/views_urls.py
View file @
2ecfecb0
...
@@ -50,4 +50,3 @@ urlpatterns = [
...
@@ -50,4 +50,3 @@ urlpatterns = [
url
(
r'^domain/(?P<pk>[0-9a-zA-Z\-]{36})/gateway/create/$'
,
views
.
DomainGatewayCreateView
.
as_view
(),
name
=
'domain-gateway-create'
),
url
(
r'^domain/(?P<pk>[0-9a-zA-Z\-]{36})/gateway/create/$'
,
views
.
DomainGatewayCreateView
.
as_view
(),
name
=
'domain-gateway-create'
),
url
(
r'^domain/gateway/(?P<pk>[0-9a-zA-Z\-]{36})/update/$'
,
views
.
DomainGatewayUpdateView
.
as_view
(),
name
=
'domain-gateway-update'
),
url
(
r'^domain/gateway/(?P<pk>[0-9a-zA-Z\-]{36})/update/$'
,
views
.
DomainGatewayUpdateView
.
as_view
(),
name
=
'domain-gateway-update'
),
]
]
apps/common/mixins.py
View file @
2ecfecb0
...
@@ -92,7 +92,7 @@ class DatetimeSearchMixin:
...
@@ -92,7 +92,7 @@ class DatetimeSearchMixin:
date_format
=
'
%
Y-
%
m-
%
d'
date_format
=
'
%
Y-
%
m-
%
d'
date_from
=
date_to
=
None
date_from
=
date_to
=
None
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
def
get
_date_range
(
self
):
date_from_s
=
self
.
request
.
GET
.
get
(
'date_from'
)
date_from_s
=
self
.
request
.
GET
.
get
(
'date_from'
)
date_to_s
=
self
.
request
.
GET
.
get
(
'date_to'
)
date_to_s
=
self
.
request
.
GET
.
get
(
'date_to'
)
...
@@ -112,6 +112,9 @@ class DatetimeSearchMixin:
...
@@ -112,6 +112,9 @@ class DatetimeSearchMixin:
)
)
else
:
else
:
self
.
date_to
=
timezone
.
now
()
self
.
date_to
=
timezone
.
now
()
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
self
.
get_date_range
()
return
super
()
.
get
(
request
,
*
args
,
**
kwargs
)
return
super
()
.
get
(
request
,
*
args
,
**
kwargs
)
...
...
apps/i18n/zh/LC_MESSAGES/django.mo
View file @
2ecfecb0
No preview for this file type
apps/i18n/zh/LC_MESSAGES/django.po
View file @
2ecfecb0
...
@@ -8,7 +8,7 @@ msgid ""
...
@@ -8,7 +8,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: 2018-07-
06 13:11
+0800\n"
"POT-Creation-Date: 2018-07-
19 18:29
+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\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"
...
@@ -32,7 +32,7 @@ msgstr ""
...
@@ -32,7 +32,7 @@ msgstr ""
#: assets/forms/asset.py:24 assets/models/asset.py:89 assets/models/user.py:112
#: assets/forms/asset.py:24 assets/models/asset.py:89 assets/models/user.py:112
#: assets/templates/assets/asset_detail.html:183
#: assets/templates/assets/asset_detail.html:183
#: assets/templates/assets/asset_detail.html:191
#: assets/templates/assets/asset_detail.html:191
#: assets/templates/assets/system_user_detail.html:17
9
perms/models.py:33
#: assets/templates/assets/system_user_detail.html:17
8
perms/models.py:33
msgid "Nodes"
msgid "Nodes"
msgstr "节点管理"
msgstr "节点管理"
...
@@ -101,7 +101,7 @@ msgstr "端口"
...
@@ -101,7 +101,7 @@ msgstr "端口"
#: assets/forms/domain.py:14 assets/forms/label.py:13
#: assets/forms/domain.py:14 assets/forms/label.py:13
#: assets/models/asset.py:237 assets/templates/assets/admin_user_list.html:25
#: assets/models/asset.py:237 assets/templates/assets/admin_user_list.html:25
#: assets/templates/assets/domain_detail.html:60
#: assets/templates/assets/domain_detail.html:60
#: assets/templates/assets/domain_list.html:
15
#: assets/templates/assets/domain_list.html:
23
#: assets/templates/assets/label_list.html:16
#: assets/templates/assets/label_list.html:16
#: assets/templates/assets/system_user_list.html:30 audits/models.py:11
#: assets/templates/assets/system_user_list.html:30 audits/models.py:11
#: audits/templates/audits/ftp_log_list.html:41
#: audits/templates/audits/ftp_log_list.html:41
...
@@ -125,7 +125,7 @@ msgstr "资产"
...
@@ -125,7 +125,7 @@ msgstr "资产"
#: assets/templates/assets/admin_user_list.html:23
#: assets/templates/assets/admin_user_list.html:23
#: assets/templates/assets/domain_detail.html:56
#: assets/templates/assets/domain_detail.html:56
#: assets/templates/assets/domain_gateway_list.html:56
#: assets/templates/assets/domain_gateway_list.html:56
#: assets/templates/assets/domain_list.html:
14
#: assets/templates/assets/domain_list.html:
22
#: assets/templates/assets/label_list.html:14
#: assets/templates/assets/label_list.html:14
#: assets/templates/assets/system_user_detail.html:58
#: assets/templates/assets/system_user_detail.html:58
#: assets/templates/assets/system_user_list.html:26 common/models.py:26
#: assets/templates/assets/system_user_list.html:26 common/models.py:26
...
@@ -356,7 +356,7 @@ msgstr "创建日期"
...
@@ -356,7 +356,7 @@ msgstr "创建日期"
#: assets/templates/assets/asset_detail.html:125
#: assets/templates/assets/asset_detail.html:125
#: assets/templates/assets/domain_detail.html:76
#: assets/templates/assets/domain_detail.html:76
#: assets/templates/assets/domain_gateway_list.html:61
#: assets/templates/assets/domain_gateway_list.html:61
#: assets/templates/assets/domain_list.html:
17
#: assets/templates/assets/domain_list.html:
25
#: assets/templates/assets/system_user_detail.html:104
#: assets/templates/assets/system_user_detail.html:104
#: assets/templates/assets/system_user_list.html:34 common/models.py:30
#: assets/templates/assets/system_user_list.html:34 common/models.py:30
#: ops/models/adhoc.py:42 perms/models.py:40 perms/models.py:83
#: ops/models/adhoc.py:42 perms/models.py:40 perms/models.py:83
...
@@ -445,7 +445,7 @@ msgstr "默认资产组"
...
@@ -445,7 +445,7 @@ msgstr "默认资产组"
#: terminal/templates/terminal/session_list.html:71 users/forms.py:282
#: terminal/templates/terminal/session_list.html:71 users/forms.py:282
#: users/models/user.py:31 users/models/user.py:333
#: users/models/user.py:31 users/models/user.py:333
#: users/templates/users/user_group_detail.html:78
#: users/templates/users/user_group_detail.html:78
#: users/templates/users/user_group_list.html:13 users/views/user.py:36
1
#: users/templates/users/user_group_list.html:13 users/views/user.py:36
7
msgid "User"
msgid "User"
msgstr "用户"
msgstr "用户"
...
@@ -685,6 +685,7 @@ msgstr "重置"
...
@@ -685,6 +685,7 @@ msgstr "重置"
#: common/templates/common/security_setting.html:71
#: common/templates/common/security_setting.html:71
#: common/templates/common/terminal_setting.html:108
#: common/templates/common/terminal_setting.html:108
#: perms/templates/perms/asset_permission_create_update.html:70
#: perms/templates/perms/asset_permission_create_update.html:70
#: terminal/templates/terminal/command_list.html:103
#: terminal/templates/terminal/session_list.html:126
#: terminal/templates/terminal/session_list.html:126
#: terminal/templates/terminal/terminal_update.html:48
#: terminal/templates/terminal/terminal_update.html:48
#: users/templates/users/_user.html:47
#: users/templates/users/_user.html:47
...
@@ -756,7 +757,7 @@ msgstr "测试"
...
@@ -756,7 +757,7 @@ msgstr "测试"
#: assets/templates/assets/domain_detail.html:24
#: assets/templates/assets/domain_detail.html:24
#: assets/templates/assets/domain_detail.html:103
#: assets/templates/assets/domain_detail.html:103
#: assets/templates/assets/domain_gateway_list.html:85
#: assets/templates/assets/domain_gateway_list.html:85
#: assets/templates/assets/domain_list.html:
42
#: assets/templates/assets/domain_list.html:
50
#: assets/templates/assets/label_list.html:38
#: assets/templates/assets/label_list.html:38
#: assets/templates/assets/system_user_detail.html:26
#: assets/templates/assets/system_user_detail.html:26
#: assets/templates/assets/system_user_list.html:89
#: assets/templates/assets/system_user_list.html:89
...
@@ -780,7 +781,7 @@ msgstr "更新"
...
@@ -780,7 +781,7 @@ msgstr "更新"
#: assets/templates/assets/domain_detail.html:28
#: assets/templates/assets/domain_detail.html:28
#: assets/templates/assets/domain_detail.html:104
#: assets/templates/assets/domain_detail.html:104
#: assets/templates/assets/domain_gateway_list.html:86
#: assets/templates/assets/domain_gateway_list.html:86
#: assets/templates/assets/domain_list.html:
43
#: assets/templates/assets/domain_list.html:
51
#: assets/templates/assets/label_list.html:39
#: assets/templates/assets/label_list.html:39
#: assets/templates/assets/system_user_detail.html:30
#: assets/templates/assets/system_user_detail.html:30
#: assets/templates/assets/system_user_list.html:90
#: assets/templates/assets/system_user_list.html:90
...
@@ -808,12 +809,13 @@ msgstr "选择节点"
...
@@ -808,12 +809,13 @@ msgstr "选择节点"
#: assets/templates/assets/admin_user_detail.html:100
#: assets/templates/assets/admin_user_detail.html:100
#: assets/templates/assets/asset_detail.html:200
#: assets/templates/assets/asset_detail.html:200
#: assets/templates/assets/asset_list.html:638
#: assets/templates/assets/asset_list.html:638
#: assets/templates/assets/system_user_detail.html:19
6
#: assets/templates/assets/system_user_detail.html:19
5
#: assets/templates/assets/system_user_list.html:139 templates/_modal.html:22
#: assets/templates/assets/system_user_list.html:139 templates/_modal.html:22
#: terminal/templates/terminal/session_detail.html:108
#: terminal/templates/terminal/session_detail.html:108
#: users/templates/users/user_detail.html:366
#: users/templates/users/user_detail.html:374
#: users/templates/users/user_detail.html:391
#: users/templates/users/user_detail.html:399
#: users/templates/users/user_detail.html:414
#: users/templates/users/user_detail.html:422
#: users/templates/users/user_detail.html:466
#: users/templates/users/user_group_create_update.html:32
#: users/templates/users/user_group_create_update.html:32
#: users/templates/users/user_group_list.html:86
#: users/templates/users/user_group_list.html:86
#: users/templates/users/user_list.html:200
#: users/templates/users/user_list.html:200
...
@@ -841,7 +843,7 @@ msgstr "比例"
...
@@ -841,7 +843,7 @@ msgstr "比例"
#: assets/templates/assets/admin_user_list.html:30
#: assets/templates/assets/admin_user_list.html:30
#: assets/templates/assets/asset_list.html:91
#: assets/templates/assets/asset_list.html:91
#: assets/templates/assets/domain_gateway_list.html:62
#: assets/templates/assets/domain_gateway_list.html:62
#: assets/templates/assets/domain_list.html:
18
#: assets/templates/assets/domain_list.html:
26
#: assets/templates/assets/label_list.html:17
#: assets/templates/assets/label_list.html:17
#: assets/templates/assets/system_user_list.html:35
#: assets/templates/assets/system_user_list.html:35
#: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:64
#: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:64
...
@@ -905,8 +907,8 @@ msgid "Refresh"
...
@@ -905,8 +907,8 @@ msgid "Refresh"
msgstr "刷新"
msgstr "刷新"
#: assets/templates/assets/asset_detail.html:300
#: assets/templates/assets/asset_detail.html:300
#: users/templates/users/user_detail.html:2
86
#: users/templates/users/user_detail.html:2
94
#: users/templates/users/user_detail.html:3
13
#: users/templates/users/user_detail.html:3
21
msgid "Update successfully!"
msgid "Update successfully!"
msgstr "更新成功"
msgstr "更新成功"
...
@@ -1002,8 +1004,9 @@ msgstr "存在资产,不能删除"
...
@@ -1002,8 +1004,9 @@ msgstr "存在资产,不能删除"
#: assets/templates/assets/asset_list.html:633
#: assets/templates/assets/asset_list.html:633
#: assets/templates/assets/system_user_list.html:134
#: assets/templates/assets/system_user_list.html:134
#: users/templates/users/user_detail.html:361
#: users/templates/users/user_detail.html:369
#: users/templates/users/user_detail.html:386
#: users/templates/users/user_detail.html:394
#: users/templates/users/user_detail.html:461
#: users/templates/users/user_group_list.html:81
#: users/templates/users/user_group_list.html:81
#: users/templates/users/user_list.html:195
#: users/templates/users/user_list.html:195
msgid "Are you sure?"
msgid "Are you sure?"
...
@@ -1043,7 +1046,7 @@ msgstr "您确定删除吗?"
...
@@ -1043,7 +1046,7 @@ msgstr "您确定删除吗?"
#: assets/templates/assets/domain_detail.html:21
#: assets/templates/assets/domain_detail.html:21
#: assets/templates/assets/domain_detail.html:64
#: assets/templates/assets/domain_detail.html:64
#: assets/templates/assets/domain_gateway_list.html:21
#: assets/templates/assets/domain_gateway_list.html:21
#: assets/templates/assets/domain_list.html:
16
#: assets/templates/assets/domain_list.html:
24
msgid "Gateway"
msgid "Gateway"
msgstr "网关"
msgstr "网关"
...
@@ -1063,7 +1066,7 @@ msgstr "创建网关"
...
@@ -1063,7 +1066,7 @@ msgstr "创建网关"
msgid "Test connection"
msgid "Test connection"
msgstr "测试连接"
msgstr "测试连接"
#: assets/templates/assets/domain_list.html:
6
assets/views/domain.py:46
#: assets/templates/assets/domain_list.html:
14
assets/views/domain.py:46
msgid "Create domain"
msgid "Create domain"
msgstr "创建网域"
msgstr "创建网域"
...
@@ -1106,20 +1109,15 @@ msgstr "家目录"
...
@@ -1106,20 +1109,15 @@ msgstr "家目录"
msgid "Uid"
msgid "Uid"
msgstr "Uid"
msgstr "Uid"
#: assets/templates/assets/system_user_detail.html:157
#: assets/templates/assets/system_user_detail.html:186
#: assets/templates/assets/system_user_detail.html:343
msgid "Clear auth"
msgstr "清除认证信息"
#: assets/templates/assets/system_user_detail.html:160
msgid "Clear"
msgstr "清除"
#: assets/templates/assets/system_user_detail.html:187
msgid "Add to node"
msgid "Add to node"
msgstr "添加到节点"
msgstr "添加到节点"
#: assets/templates/assets/system_user_detail.html:343
#: assets/templates/assets/system_user_detail.html:353
msgid "Clear auth"
msgstr "清除认证信息"
#: assets/templates/assets/system_user_detail.html:353
msgid "success"
msgid "success"
msgstr "成功"
msgstr "成功"
...
@@ -1238,6 +1236,7 @@ msgstr "文件名"
...
@@ -1238,6 +1236,7 @@ msgstr "文件名"
#: audits/models.py:15 audits/templates/audits/ftp_log_list.html:77
#: audits/models.py:15 audits/templates/audits/ftp_log_list.html:77
#: ops/templates/ops/task_list.html:39 users/models/authentication.py:66
#: ops/templates/ops/task_list.html:39 users/models/authentication.py:66
#: users/templates/users/user_detail.html:443
msgid "Success"
msgid "Success"
msgstr "成功"
msgstr "成功"
...
@@ -1854,7 +1853,7 @@ msgstr "选择用户"
...
@@ -1854,7 +1853,7 @@ msgstr "选择用户"
#: perms/templates/perms/asset_permission_list.html:136 templates/_nav.html:14
#: perms/templates/perms/asset_permission_list.html:136 templates/_nav.html:14
#: users/models/group.py:23 users/models/user.py:55
#: users/models/group.py:23 users/models/user.py:55
#: users/templates/users/_select_user_modal.html:16
#: users/templates/users/_select_user_modal.html:16
#: users/templates/users/user_detail.html:
192
#: users/templates/users/user_detail.html:
200
#: users/templates/users/user_list.html:26
#: users/templates/users/user_list.html:26
msgid "User group"
msgid "User group"
msgstr "用户组"
msgstr "用户组"
...
@@ -1907,7 +1906,7 @@ msgid "Add node to this permission"
...
@@ -1907,7 +1906,7 @@ msgid "Add node to this permission"
msgstr "添加节点"
msgstr "添加节点"
#: perms/templates/perms/asset_permission_asset.html:125
#: perms/templates/perms/asset_permission_asset.html:125
#: users/templates/users/user_detail.html:2
09
#: users/templates/users/user_detail.html:2
17
msgid "Join"
msgid "Join"
msgstr "加入"
msgstr "加入"
...
@@ -2004,7 +2003,7 @@ msgstr "文档"
...
@@ -2004,7 +2003,7 @@ msgstr "文档"
#: users/templates/users/user_profile.html:17
#: users/templates/users/user_profile.html:17
#: users/templates/users/user_profile_update.html:37
#: users/templates/users/user_profile_update.html:37
#: users/templates/users/user_profile_update.html:57
#: users/templates/users/user_profile_update.html:57
#: users/templates/users/user_pubkey_update.html:37 users/views/user.py:34
3
#: users/templates/users/user_pubkey_update.html:37 users/views/user.py:34
9
msgid "Profile"
msgid "Profile"
msgstr "个人信息"
msgstr "个人信息"
...
@@ -2061,13 +2060,13 @@ msgstr "关闭"
...
@@ -2061,13 +2060,13 @@ msgstr "关闭"
#: templates/_nav.html:10 users/views/group.py:28 users/views/group.py:44
#: templates/_nav.html:10 users/views/group.py:28 users/views/group.py:44
#: users/views/group.py:62 users/views/group.py:79 users/views/group.py:95
#: users/views/group.py:62 users/views/group.py:79 users/views/group.py:95
#: users/views/login.py:33
0 users/views/login.py:388 users/views/user.py:65
#: users/views/login.py:33
2 users/views/login.py:390 users/views/user.py:67
#: users/views/user.py:8
0 users/views/user.py:102 users/views/user.py:175
#: users/views/user.py:8
2 users/views/user.py:104 users/views/user.py:180
#: users/views/user.py:33
0 users/views/user.py:380 users/views/user.py:415
#: users/views/user.py:33
6 users/views/user.py:386 users/views/user.py:421
msgid "Users"
msgid "Users"
msgstr "用户管理"
msgstr "用户管理"
#: templates/_nav.html:13 users/views/user.py:6
6
#: templates/_nav.html:13 users/views/user.py:6
8
msgid "User list"
msgid "User list"
msgstr "用户列表"
msgstr "用户列表"
...
@@ -2095,7 +2094,7 @@ msgstr "命令记录"
...
@@ -2095,7 +2094,7 @@ msgstr "命令记录"
msgid "Web terminal"
msgid "Web terminal"
msgstr "Web终端"
msgstr "Web终端"
#: templates/_nav.html:51 terminal/views/command.py:4
7
#: templates/_nav.html:51 terminal/views/command.py:4
9
#: terminal/views/session.py:75 terminal/views/session.py:93
#: terminal/views/session.py:75 terminal/views/session.py:93
#: terminal/views/session.py:115 terminal/views/terminal.py:31
#: terminal/views/session.py:115 terminal/views/terminal.py:31
#: terminal/views/terminal.py:46 terminal/views/terminal.py:58
#: terminal/views/terminal.py:46 terminal/views/terminal.py:58
...
@@ -2204,13 +2203,17 @@ msgstr "参数"
...
@@ -2204,13 +2203,17 @@ msgstr "参数"
msgid "Goto"
msgid "Goto"
msgstr "转到"
msgstr "转到"
#: terminal/templates/terminal/command_list.html:99
msgid "Export command"
msgstr "导出命令"
#: terminal/templates/terminal/session_detail.html:17
#: terminal/templates/terminal/session_detail.html:17
#: terminal/views/session.py:116
#: terminal/views/session.py:116
msgid "Session detail"
msgid "Session detail"
msgstr "会话详情"
msgstr "会话详情"
#: terminal/templates/terminal/session_detail.html:28
#: terminal/templates/terminal/session_detail.html:28
#: terminal/views/command.py:
48
#: terminal/views/command.py:
50
msgid "Command list"
msgid "Command list"
msgstr "命令记录列表"
msgstr "命令记录列表"
...
@@ -2326,7 +2329,7 @@ msgid ""
...
@@ -2326,7 +2329,7 @@ msgid ""
"You should use your ssh client tools connect terminal: {} <br /> <br />{}"
"You should use your ssh client tools connect terminal: {} <br /> <br />{}"
msgstr "你可以使用ssh客户端工具连接终端"
msgstr "你可以使用ssh客户端工具连接终端"
#: users/api.py:2
08
users/templates/users/login.html:50
#: users/api.py:2
26
users/templates/users/login.html:50
msgid "Log in frequently and try again later"
msgid "Log in frequently and try again later"
msgstr "登录频繁, 稍后重试"
msgstr "登录频繁, 稍后重试"
...
@@ -2405,7 +2408,7 @@ msgstr ""
...
@@ -2405,7 +2408,7 @@ msgstr ""
msgid "Paste user id_rsa.pub here."
msgid "Paste user id_rsa.pub here."
msgstr "复制用户公钥到这里"
msgstr "复制用户公钥到这里"
#: users/forms.py:73 users/templates/users/user_detail.html:20
0
#: users/forms.py:73 users/templates/users/user_detail.html:20
8
msgid "Join user groups"
msgid "Join user groups"
msgstr "添加到用户组"
msgstr "添加到用户组"
...
@@ -2701,7 +2704,7 @@ msgid "Can't provide security? Please contact the administrator!"
...
@@ -2701,7 +2704,7 @@ msgid "Can't provide security? Please contact the administrator!"
msgstr "如果不能提供MFA验证码,请联系管理员!"
msgstr "如果不能提供MFA验证码,请联系管理员!"
#: users/templates/users/reset_password.html:46
#: users/templates/users/reset_password.html:46
#: users/templates/users/user_detail.html:3
52
users/utils.py:80
#: users/templates/users/user_detail.html:3
60
users/utils.py:80
msgid "Reset password"
msgid "Reset password"
msgstr "重置密码"
msgstr "重置密码"
...
@@ -2727,7 +2730,7 @@ msgid "Setting"
...
@@ -2727,7 +2730,7 @@ msgid "Setting"
msgstr "设置"
msgstr "设置"
#: users/templates/users/user_create.html:4
#: users/templates/users/user_create.html:4
#: users/templates/users/user_list.html:16 users/views/user.py:8
0
#: users/templates/users/user_list.html:16 users/views/user.py:8
2
msgid "Create user"
msgid "Create user"
msgstr "创建用户"
msgstr "创建用户"
...
@@ -2736,7 +2739,7 @@ msgid "Reset link will be generated and sent to the user. "
...
@@ -2736,7 +2739,7 @@ msgid "Reset link will be generated and sent to the user. "
msgstr "生成重置密码连接,通过邮件发送给用户"
msgstr "生成重置密码连接,通过邮件发送给用户"
#: users/templates/users/user_detail.html:19
#: users/templates/users/user_detail.html:19
#: users/templates/users/user_granted_asset.html:18 users/views/user.py:1
76
#: users/templates/users/user_granted_asset.html:18 users/views/user.py:1
81
msgid "User detail"
msgid "User detail"
msgstr "用户详情"
msgstr "用户详情"
...
@@ -2773,44 +2776,57 @@ msgstr "发送"
...
@@ -2773,44 +2776,57 @@ msgstr "发送"
msgid "Send reset ssh key mail"
msgid "Send reset ssh key mail"
msgstr "发送重置密钥邮件"
msgstr "发送重置密钥邮件"
#: users/templates/users/user_detail.html:295
#: users/templates/users/user_detail.html:186
#: users/templates/users/user_detail.html:446
msgid "Unblock user"
msgstr "解除登录限制"
#: users/templates/users/user_detail.html:189
msgid "Unblock"
msgstr "解除"
#: users/templates/users/user_detail.html:303
msgid "Goto profile page enable MFA"
msgid "Goto profile page enable MFA"
msgstr "请去个人信息页面启用自己的MFA"
msgstr "请去个人信息页面启用自己的MFA"
#: users/templates/users/user_detail.html:35
1
#: users/templates/users/user_detail.html:35
9
msgid "An e-mail has been sent to the user`s mailbox."
msgid "An e-mail has been sent to the user`s mailbox."
msgstr "已发送邮件到用户邮箱"
msgstr "已发送邮件到用户邮箱"
#: users/templates/users/user_detail.html:3
62
#: users/templates/users/user_detail.html:3
70
msgid "This will reset the user password and send a reset mail"
msgid "This will reset the user password and send a reset mail"
msgstr "将失效用户当前密码,并发送重设密码邮件到用户邮箱"
msgstr "将失效用户当前密码,并发送重设密码邮件到用户邮箱"
#: users/templates/users/user_detail.html:3
76
#: users/templates/users/user_detail.html:3
84
msgid ""
msgid ""
"The reset-ssh-public-key E-mail has been sent successfully. Please inform "
"The reset-ssh-public-key E-mail has been sent successfully. Please inform "
"the user to update his new ssh public key."
"the user to update his new ssh public key."
msgstr "重设密钥邮件将会发送到用户邮箱"
msgstr "重设密钥邮件将会发送到用户邮箱"
#: users/templates/users/user_detail.html:3
77
#: users/templates/users/user_detail.html:3
85
msgid "Reset SSH public key"
msgid "Reset SSH public key"
msgstr "重置SSH密钥"
msgstr "重置SSH密钥"
#: users/templates/users/user_detail.html:3
87
#: users/templates/users/user_detail.html:3
95
msgid "This will reset the user public key and send a reset mail"
msgid "This will reset the user public key and send a reset mail"
msgstr "将会失效用户当前密钥,并发送重置邮件到用户邮箱"
msgstr "将会失效用户当前密钥,并发送重置邮件到用户邮箱"
#: users/templates/users/user_detail.html:4
04
#: users/templates/users/user_detail.html:4
12
#: users/templates/users/user_profile.html:211
#: users/templates/users/user_profile.html:211
msgid "Successfully updated the SSH public key."
msgid "Successfully updated the SSH public key."
msgstr "更新ssh密钥成功"
msgstr "更新ssh密钥成功"
#: users/templates/users/user_detail.html:4
05
#: users/templates/users/user_detail.html:4
13
#: users/templates/users/user_detail.html:4
09
#: users/templates/users/user_detail.html:4
17
#: users/templates/users/user_profile.html:212
#: users/templates/users/user_profile.html:212
#: users/templates/users/user_profile.html:217
#: users/templates/users/user_profile.html:217
msgid "User SSH public key update"
msgid "User SSH public key update"
msgstr "ssh密钥"
msgstr "ssh密钥"
#: users/templates/users/user_detail.html:462
msgid "After unlocking the user, the user can log in normally."
msgstr "解除用户登录限制后,此用户即可正常登录"
#: users/templates/users/user_group_create_update.html:31
#: users/templates/users/user_group_create_update.html:31
msgid "Cancel"
msgid "Cancel"
msgstr "取消"
msgstr "取消"
...
@@ -2867,8 +2883,8 @@ msgstr "用户删除失败"
...
@@ -2867,8 +2883,8 @@ msgstr "用户删除失败"
msgid "Administrator Settings force MFA login"
msgid "Administrator Settings force MFA login"
msgstr "管理员设置强制使用MFA登录"
msgstr "管理员设置强制使用MFA登录"
#: users/templates/users/user_profile.html:116 users/views/user.py:2
05
#: users/templates/users/user_profile.html:116 users/views/user.py:2
11
#: users/views/user.py:2
59
#: users/views/user.py:2
65
msgid "User groups"
msgid "User groups"
msgstr "用户组"
msgstr "用户组"
...
@@ -2914,7 +2930,7 @@ msgid ""
...
@@ -2914,7 +2930,7 @@ msgid ""
"corresponding private key."
"corresponding private key."
msgstr "新的公钥已设置成功,请下载对应的私钥"
msgstr "新的公钥已设置成功,请下载对应的私钥"
#: users/templates/users/user_update.html:4 users/views/user.py:10
3
#: users/templates/users/user_update.html:4 users/views/user.py:10
5
msgid "Update user"
msgid "Update user"
msgstr "更新用户"
msgstr "更新用户"
...
@@ -3068,106 +3084,112 @@ msgstr "更新用户组"
...
@@ -3068,106 +3084,112 @@ msgstr "更新用户组"
msgid "User group granted asset"
msgid "User group granted asset"
msgstr "用户组授权资产"
msgstr "用户组授权资产"
#: users/views/login.py:7
5
#: users/views/login.py:7
6
msgid "Please enable cookies and try again."
msgid "Please enable cookies and try again."
msgstr "设置你的浏览器支持cookie"
msgstr "设置你的浏览器支持cookie"
#: users/views/login.py:1
78 users/views/user.py:500 users/views/user.py:525
#: users/views/login.py:1
80 users/views/user.py:506 users/views/user.py:531
msgid "MFA code invalid"
msgid "MFA code invalid"
msgstr "MFA码认证失败"
msgstr "MFA码认证失败"
#: users/views/login.py:20
7
#: users/views/login.py:20
9
msgid "Logout success"
msgid "Logout success"
msgstr "退出登录成功"
msgstr "退出登录成功"
#: users/views/login.py:2
08
#: users/views/login.py:2
10
msgid "Logout success, return login page"
msgid "Logout success, return login page"
msgstr "退出登录成功,返回到登录页面"
msgstr "退出登录成功,返回到登录页面"
#: users/views/login.py:22
4
#: users/views/login.py:22
6
msgid "Email address invalid, please input again"
msgid "Email address invalid, please input again"
msgstr "邮箱地址错误,重新输入"
msgstr "邮箱地址错误,重新输入"
#: users/views/login.py:23
7
#: users/views/login.py:23
9
msgid "Send reset password message"
msgid "Send reset password message"
msgstr "发送重置密码邮件"
msgstr "发送重置密码邮件"
#: users/views/login.py:2
38
#: users/views/login.py:2
40
msgid "Send reset password mail success, login your mail box and follow it "
msgid "Send reset password mail success, login your mail box and follow it "
msgstr ""
msgstr ""
"发送重置邮件成功, 请登录邮箱查看, 按照提示操作 (如果没收到,请等待3-5分钟)"
"发送重置邮件成功, 请登录邮箱查看, 按照提示操作 (如果没收到,请等待3-5分钟)"
#: users/views/login.py:25
1
#: users/views/login.py:25
3
msgid "Reset password success"
msgid "Reset password success"
msgstr "重置密码成功"
msgstr "重置密码成功"
#: users/views/login.py:25
2
#: users/views/login.py:25
4
msgid "Reset password success, return to login page"
msgid "Reset password success, return to login page"
msgstr "重置密码成功,返回到登录页面"
msgstr "重置密码成功,返回到登录页面"
#: users/views/login.py:27
3 users/views/login.py:286
#: users/views/login.py:27
5 users/views/login.py:288
msgid "Token invalid or expired"
msgid "Token invalid or expired"
msgstr "Token错误或失效"
msgstr "Token错误或失效"
#: users/views/login.py:28
2
#: users/views/login.py:28
4
msgid "Password not same"
msgid "Password not same"
msgstr "密码不一致"
msgstr "密码不一致"
#: users/views/login.py:29
2 users/views/user.py:118 users/views/user.py:398
#: users/views/login.py:29
4 users/views/user.py:120 users/views/user.py:404
msgid "* Your password does not meet the requirements"
msgid "* Your password does not meet the requirements"
msgstr "* 您的密码不符合要求"
msgstr "* 您的密码不符合要求"
#: users/views/login.py:33
0
#: users/views/login.py:33
2
msgid "First login"
msgid "First login"
msgstr "首次登陆"
msgstr "首次登陆"
#: users/views/login.py:3
89
#: users/views/login.py:3
91
msgid "Login log list"
msgid "Login log list"
msgstr "登录日志"
msgstr "登录日志"
#: users/views/user.py:1
29
#: users/views/user.py:1
31
msgid "Bulk update user success"
msgid "Bulk update user success"
msgstr "批量更新用户成功"
msgstr "批量更新用户成功"
#: users/views/user.py:2
34
#: users/views/user.py:2
40
msgid "Invalid file."
msgid "Invalid file."
msgstr "文件不合法"
msgstr "文件不合法"
#: users/views/user.py:33
1
#: users/views/user.py:33
7
msgid "User granted assets"
msgid "User granted assets"
msgstr "用户授权资产"
msgstr "用户授权资产"
#: users/views/user.py:36
2
#: users/views/user.py:36
8
msgid "Profile setting"
msgid "Profile setting"
msgstr "个人信息设置"
msgstr "个人信息设置"
#: users/views/user.py:38
1
#: users/views/user.py:38
7
msgid "Password update"
msgid "Password update"
msgstr "密码更新"
msgstr "密码更新"
#: users/views/user.py:4
16
#: users/views/user.py:4
22
msgid "Public key update"
msgid "Public key update"
msgstr "密钥更新"
msgstr "密钥更新"
#: users/views/user.py:4
57
#: users/views/user.py:4
63
msgid "Password invalid"
msgid "Password invalid"
msgstr "用户名或密码无效"
msgstr "用户名或密码无效"
#: users/views/user.py:55
1
#: users/views/user.py:55
7
msgid "MFA enable success"
msgid "MFA enable success"
msgstr "MFA 绑定成功"
msgstr "MFA 绑定成功"
#: users/views/user.py:55
2
#: users/views/user.py:55
8
msgid "MFA enable success, return login page"
msgid "MFA enable success, return login page"
msgstr "MFA 绑定成功,返回到登录页面"
msgstr "MFA 绑定成功,返回到登录页面"
#: users/views/user.py:5
54
#: users/views/user.py:5
60
msgid "MFA disable success"
msgid "MFA disable success"
msgstr "MFA 解绑成功"
msgstr "MFA 解绑成功"
#: users/views/user.py:5
55
#: users/views/user.py:5
61
msgid "MFA disable success, return login page"
msgid "MFA disable success, return login page"
msgstr "MFA 解绑成功,返回登录页面"
msgstr "MFA 解绑成功,返回登录页面"
#~ msgid "Unblock user successfully. "
#~ msgstr "解除登录限制成功"
#~ msgid "Clear"
#~ msgstr "清除"
#~ msgid "MFA setting"
#~ msgid "MFA setting"
#~ msgstr "MFA 设置"
#~ msgstr "MFA 设置"
apps/jumpserver/settings.py
View file @
2ecfecb0
...
@@ -341,6 +341,7 @@ AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
...
@@ -341,6 +341,7 @@ AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
AUTH_LDAP_CONNECTION_OPTIONS
=
{
AUTH_LDAP_CONNECTION_OPTIONS
=
{
ldap
.
OPT_TIMEOUT
:
5
ldap
.
OPT_TIMEOUT
:
5
}
}
AUTH_LDAP_GROUP_CACHE_TIMEOUT
=
1
AUTH_LDAP_ALWAYS_UPDATE_USER
=
True
AUTH_LDAP_ALWAYS_UPDATE_USER
=
True
AUTH_LDAP_BACKEND
=
'django_auth_ldap.backend.LDAPBackend'
AUTH_LDAP_BACKEND
=
'django_auth_ldap.backend.LDAPBackend'
...
...
apps/jumpserver/views.py
View file @
2ecfecb0
...
@@ -10,6 +10,7 @@ from users.models import User
...
@@ -10,6 +10,7 @@ from users.models import User
from
assets.models
import
Asset
from
assets.models
import
Asset
from
terminal.models
import
Session
from
terminal.models
import
Session
from
common.permissions
import
AdminUserRequiredMixin
from
common.permissions
import
AdminUserRequiredMixin
from
orgs.utils
import
current_org
class
IndexView
(
AdminUserRequiredMixin
,
TemplateView
):
class
IndexView
(
AdminUserRequiredMixin
,
TemplateView
):
...
@@ -27,7 +28,7 @@ class IndexView(AdminUserRequiredMixin, TemplateView):
...
@@ -27,7 +28,7 @@ class IndexView(AdminUserRequiredMixin, TemplateView):
@staticmethod
@staticmethod
def
get_user_count
():
def
get_user_count
():
return
User
.
objects
.
filter
(
role__in
=
(
'Admin'
,
'User'
)
)
.
count
()
return
current_org
.
get_org_users
(
)
.
count
()
@staticmethod
@staticmethod
def
get_asset_count
():
def
get_asset_count
():
...
@@ -49,7 +50,6 @@ class IndexView(AdminUserRequiredMixin, TemplateView):
...
@@ -49,7 +50,6 @@ class IndexView(AdminUserRequiredMixin, TemplateView):
def
get_week_login_asset_count
(
self
):
def
get_week_login_asset_count
(
self
):
return
self
.
session_week
.
count
()
return
self
.
session_week
.
count
()
# return self.session_week.values('asset').distinct().count()
def
get_month_day_metrics
(
self
):
def
get_month_day_metrics
(
self
):
month_str
=
[
d
.
strftime
(
'
%
m-
%
d'
)
for
d
in
self
.
session_month_dates
]
or
[
'0'
]
month_str
=
[
d
.
strftime
(
'
%
m-
%
d'
)
for
d
in
self
.
session_month_dates
]
or
[
'0'
]
...
...
apps/orgs/models.py
View file @
2ecfecb0
...
@@ -55,9 +55,11 @@ class Organization(models.Model):
...
@@ -55,9 +55,11 @@ class Organization(models.Model):
def
get_org_users
(
self
):
def
get_org_users
(
self
):
from
users.models
import
User
from
users.models
import
User
if
self
.
is_default
():
if
self
.
is_default
():
return
User
.
objects
.
filter
(
orgs__isnull
=
True
)
users
=
User
.
objects
.
filter
(
orgs__isnull
=
True
)
else
:
else
:
return
self
.
users
.
all
()
users
=
self
.
users
.
all
()
users
=
users
.
exclude
(
role
=
User
.
ROLE_APP
)
return
users
def
get_org_admins
(
self
):
def
get_org_admins
(
self
):
if
self
.
is_real
():
if
self
.
is_real
():
...
...
apps/perms/api.py
View file @
2ecfecb0
...
@@ -5,6 +5,7 @@ from django.shortcuts import get_object_or_404
...
@@ -5,6 +5,7 @@ from django.shortcuts import get_object_or_404
from
rest_framework.views
import
APIView
,
Response
from
rest_framework.views
import
APIView
,
Response
from
rest_framework.generics
import
ListAPIView
,
get_object_or_404
,
RetrieveUpdateAPIView
from
rest_framework.generics
import
ListAPIView
,
get_object_or_404
,
RetrieveUpdateAPIView
from
rest_framework
import
viewsets
from
rest_framework
import
viewsets
from
rest_framework.pagination
import
LimitOffsetPagination
from
common.utils
import
set_or_append_attr_bulk
,
get_object_or_none
from
common.utils
import
set_or_append_attr_bulk
,
get_object_or_none
from
common.permissions
import
IsValidUser
,
IsOrgAdmin
,
IsOrgAdminOrAppUser
from
common.permissions
import
IsValidUser
,
IsOrgAdmin
,
IsOrgAdminOrAppUser
...
@@ -72,10 +73,7 @@ class UserGrantedAssetsApi(ListAPIView):
...
@@ -72,10 +73,7 @@ class UserGrantedAssetsApi(ListAPIView):
util
=
AssetPermissionUtil
(
user
)
util
=
AssetPermissionUtil
(
user
)
for
k
,
v
in
util
.
get_assets
()
.
items
():
for
k
,
v
in
util
.
get_assets
()
.
items
():
if
k
.
is_unixlike
():
system_users_granted
=
[
s
for
s
in
v
if
s
.
protocol
==
k
.
protocol
]
system_users_granted
=
[
s
for
s
in
v
if
s
.
protocol
in
[
'ssh'
,
'telnet'
]]
else
:
system_users_granted
=
[
s
for
s
in
v
if
s
.
protocol
in
[
'rdp'
,
'telnet'
]]
k
.
system_users_granted
=
system_users_granted
k
.
system_users_granted
=
system_users_granted
queryset
.
append
(
k
)
queryset
.
append
(
k
)
return
queryset
return
queryset
...
@@ -123,10 +121,7 @@ class UserGrantedNodesWithAssetsApi(ListAPIView):
...
@@ -123,10 +121,7 @@ class UserGrantedNodesWithAssetsApi(ListAPIView):
for
node
,
_assets
in
nodes
.
items
():
for
node
,
_assets
in
nodes
.
items
():
assets
=
_assets
.
keys
()
assets
=
_assets
.
keys
()
for
k
,
v
in
_assets
.
items
():
for
k
,
v
in
_assets
.
items
():
if
k
.
is_unixlike
():
system_users_granted
=
[
s
for
s
in
v
if
s
.
protocol
==
k
.
protocol
]
system_users_granted
=
[
s
for
s
in
v
if
s
.
protocol
in
[
'ssh'
,
'telnet'
]]
else
:
system_users_granted
=
[
s
for
s
in
v
if
s
.
protocol
in
[
'rdp'
,
'telnet'
]]
k
.
system_users_granted
=
system_users_granted
k
.
system_users_granted
=
system_users_granted
node
.
assets_granted
=
assets
node
.
assets_granted
=
assets
queryset
.
append
(
node
)
queryset
.
append
(
node
)
...
...
apps/perms/urls/views_urls.py
View file @
2ecfecb0
...
@@ -6,13 +6,11 @@ from .. import views
...
@@ -6,13 +6,11 @@ from .. import views
app_name
=
'perms'
app_name
=
'perms'
urlpatterns
=
[
urlpatterns
=
[
url
(
r'^asset-permission$'
,
views
.
AssetPermissionListView
.
as_view
(),
name
=
'asset-permission-list'
),
url
(
r'^asset-permission
/
$'
,
views
.
AssetPermissionListView
.
as_view
(),
name
=
'asset-permission-list'
),
url
(
r'^asset-permission/create$'
,
views
.
AssetPermissionCreateView
.
as_view
(),
name
=
'asset-permission-create'
),
url
(
r'^asset-permission/create
/
$'
,
views
.
AssetPermissionCreateView
.
as_view
(),
name
=
'asset-permission-create'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/update$'
,
views
.
AssetPermissionUpdateView
.
as_view
(),
name
=
'asset-permission-update'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/update
/
$'
,
views
.
AssetPermissionUpdateView
.
as_view
(),
name
=
'asset-permission-update'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})$'
,
views
.
AssetPermissionDetailView
.
as_view
(),
name
=
'asset-permission-detail'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})
/
$'
,
views
.
AssetPermissionDetailView
.
as_view
(),
name
=
'asset-permission-detail'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/delete$'
,
views
.
AssetPermissionDeleteView
.
as_view
(),
name
=
'asset-permission-delete'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/delete
/
$'
,
views
.
AssetPermissionDeleteView
.
as_view
(),
name
=
'asset-permission-delete'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/user$'
,
views
.
AssetPermissionUserView
.
as_view
(),
name
=
'asset-permission-user-list'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/user
/
$'
,
views
.
AssetPermissionUserView
.
as_view
(),
name
=
'asset-permission-user-list'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/asset$'
,
views
.
AssetPermissionAssetView
.
as_view
(),
name
=
'asset-permission-asset-list'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/asset
/
$'
,
views
.
AssetPermissionAssetView
.
as_view
(),
name
=
'asset-permission-asset-list'
),
]
]
apps/templates/_footer.html
View file @
2ecfecb0
<div
class=
"footer fixed"
>
<div
class=
"footer fixed"
>
<div
class=
"pull-right"
>
<div
class=
"pull-right"
>
Version
<strong>
1.3.
2
-{% include '_build.html' %}
</strong>
GPLv2.
Version
<strong>
1.3.
3
-{% include '_build.html' %}
</strong>
GPLv2.
<!--<img style="display: none" src="http://www.jumpserver.org/img/evaluate_avatar1.jpg">-->
<!--<img style="display: none" src="http://www.jumpserver.org/img/evaluate_avatar1.jpg">-->
</div>
</div>
<div>
<div>
...
...
apps/terminal/api.py
View file @
2ecfecb0
...
@@ -4,6 +4,7 @@ from collections import OrderedDict
...
@@ -4,6 +4,7 @@ from collections import OrderedDict
import
logging
import
logging
import
os
import
os
import
uuid
import
uuid
import
copy
from
django.core.cache
import
cache
from
django.core.cache
import
cache
from
django.shortcuts
import
get_object_or_404
,
redirect
from
django.shortcuts
import
get_object_or_404
,
redirect
...
@@ -310,6 +311,7 @@ class SessionReplayViewSet(viewsets.ViewSet):
...
@@ -310,6 +311,7 @@ class SessionReplayViewSet(viewsets.ViewSet):
def
retrieve
(
self
,
request
,
*
args
,
**
kwargs
):
def
retrieve
(
self
,
request
,
*
args
,
**
kwargs
):
session_id
=
kwargs
.
get
(
'pk'
)
session_id
=
kwargs
.
get
(
'pk'
)
self
.
session
=
get_object_or_404
(
Session
,
id
=
session_id
)
self
.
session
=
get_object_or_404
(
Session
,
id
=
session_id
)
# 新版本和老版本的文件后缀不同
# 新版本和老版本的文件后缀不同
session_path
=
self
.
get_session_path
()
# 存在外部存储上的路径
session_path
=
self
.
get_session_path
()
# 存在外部存储上的路径
local_path
=
self
.
get_local_path
()
local_path
=
self
.
get_local_path
()
...
...
apps/terminal/templates/terminal/command_list.html
View file @
2ecfecb0
...
@@ -92,27 +92,52 @@
...
@@ -92,27 +92,52 @@
{% endfor %}
{% endfor %}
</tbody>
</tbody>
</table>
</table>
<div
id=
"actions"
class=
""
>
<div
class=
"input-group"
>
<select
class=
"form-control m-b"
style=
"width: auto"
id=
"slct_bulk_update"
>
<option
value=
"export"
>
{% trans 'Export command' %}
</option>
</select>
<div
class=
"input-group-btn pull-left"
style=
"padding-left: 5px;"
>
<button
id=
'btn_bulk_update'
style=
"height: 32px;"
class=
"btn btn-sm btn-primary"
>
{% trans 'Submit' %}
</button>
</div>
</div>
</div>
{% endblock %}
{% endblock %}
{% block custom_foot_js %}
{% block custom_foot_js %}
<script
src=
"{% static "
js
/
plugins
/
footable
/
footable
.
all
.
min
.
js
"
%}"
></script>
<script
src=
"{% static "
js
/
plugins
/
footable
/
footable
.
all
.
min
.
js
"
%}"
></script>
<script
src=
"{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"
></script>
<script
src=
"{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"
></script>
<script>
<script>
$
(
document
).
ready
(
function
()
{
$
(
document
).
ready
(
function
()
{
$
(
'.footable'
).
footable
();
$
(
'.footable'
).
footable
();
$
(
'.select2'
).
select2
({
$
(
'.select2'
).
select2
({
dropdownAutoWidth
:
true
,
dropdownAutoWidth
:
true
,
width
:
'auto'
width
:
'auto'
});
});
$
(
'#date .input-daterange'
).
datepicker
({
$
(
'#date .input-daterange'
).
datepicker
({
format
:
"yyyy-mm-dd"
,
format
:
"yyyy-mm-dd"
,
todayBtn
:
"linked"
,
todayBtn
:
"linked"
,
keyboardNavigation
:
false
,
keyboardNavigation
:
false
,
forceParse
:
false
,
forceParse
:
false
,
calendarWeeks
:
true
,
calendarWeeks
:
true
,
autoclose
:
true
autoclose
:
true
});
});
});
})
.
on
(
'click'
,
'#btn_bulk_update'
,
function
(){
var
action
=
$
(
'#slct_bulk_update'
).
val
();
var
param_action
=
'&action='
+
action
;
var
local_params
=
window
.
location
.
search
;
if
(
!
local_params
){
param_action
=
'?action='
+
action
;
}
var
params
=
local_params
+
param_action
;
var
pathname
=
window
.
location
.
pathname
+
'export/'
;
var
url
=
pathname
+
params
;
window
.
open
(
url
);
});
</script>
</script>
{% endblock %}
{% endblock %}
...
...
apps/terminal/templates/terminal/command_report.html
0 → 100644
View file @
2ecfecb0
{% load common_tags %}
{% load static %}
<!DOCTYPE html>
<html
lang=
"en"
>
<head>
<meta
charset=
"UTF-8"
>
<title>
Command Report
</title>
<style>
*
{
margin
:
0
;
padding
:
0
;
}
.background
{
background-color
:
#535659
;
padding-top
:
50px
;
padding-bottom
:
50px
;
}
.paper
{
margin-left
:
23%
;
margin-right
:
24%
;
border
:
solid
;
padding
:
50px
;
background-color
:
#fff
;
}
h2
{
font-style
:
italic
;
text-align
:
center
;
}
.info
{
width
:
200px
;
margin-left
:
450px
;
font-style
:
italic
;
text-align
:
left
;
padding-top
:
20px
;
padding-bottom
:
20px
;
}
.command
{
margin-left
:
10px
;
}
.command-desc
{
font-size
:
12px
;
}
.command-desc
span
{
float
:
right
;
}
.command-input
{
{#
font-style
:
italic
;
#
}
font-size
:
15px
;
margin-top
:
10px
;
margin-bottom
:
10px
;
}
.command-input
span
{
font-size
:
13px
;
}
.hr-line-dashed
{
border-top
:
1px
dashed
#000
;
color
:
#000
;
background-color
:
#fff
;
height
:
1px
;
margin
:
20px
0
;
}
pre
{
font-size
:
12px
;
}
</style>
</head>
<body>
<div
class=
"background"
>
<div
class=
"paper"
>
<h2>
Command Report
</h2>
<div
class=
"info"
>
<p>
total: {{ total_count }}
</p>
<p>
date: {{ now | ts_to_date }}
</p>
</div>
<div
class=
"hr-line-dashed"
></div>
<div>
{% for command in queryset %}
<div
class=
"command"
>
<p
class=
"command-desc"
>
[{{ command.user}} {{ command.system_user }}@{{ command.asset }} {{ command.timestamp | ts_to_date }}]
<span>
{{ forloop.counter }}
</span>
</p>
<p
class=
"command-input"
><span>
$
</span>
{{ command.input }}
</p>
<pre>
{{ command.output }}
</pre>
</div>
<div
class=
"hr-line-dashed"
></div>
{% endfor %}
</div>
</div>
</div>
</body>
</html>
\ No newline at end of file
apps/terminal/urls/views_urls.py
View file @
2ecfecb0
...
@@ -24,5 +24,6 @@ urlpatterns = [
...
@@ -24,5 +24,6 @@ urlpatterns = [
# Command view
# Command view
url
(
r'^command/$'
,
views
.
CommandListView
.
as_view
(),
name
=
'command-list'
),
url
(
r'^command/$'
,
views
.
CommandListView
.
as_view
(),
name
=
'command-list'
),
url
(
r'^command/export/$'
,
views
.
CommandExportView
.
as_view
(),
name
=
'command-export'
)
]
]
apps/terminal/views/command.py
View file @
2ecfecb0
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
#
#
from
django.views.generic
import
ListView
from
django.views.generic
import
ListView
,
View
from
django.conf
import
settings
from
django.conf
import
settings
from
django.utils
import
timezone
from
django.utils.translation
import
ugettext
as
_
from
django.utils.translation
import
ugettext
as
_
from
django.http
import
HttpResponse
from
django.template
import
loader
import
time
from
common.mixins
import
DatetimeSearchMixin
from
common.mixins
import
DatetimeSearchMixin
from
common.permissions
import
AdminUserRequiredMixin
from
common.permissions
import
AdminUserRequiredMixin
...
@@ -12,7 +14,7 @@ from ..models import Command
...
@@ -12,7 +14,7 @@ from ..models import Command
from
..
import
utils
from
..
import
utils
from
..backends
import
get_multi_command_storage
from
..backends
import
get_multi_command_storage
__all__
=
[
'CommandListView'
]
__all__
=
[
'CommandListView'
,
'CommandExportView'
]
common_storage
=
get_multi_command_storage
()
common_storage
=
get_multi_command_storage
()
...
@@ -61,7 +63,43 @@ class CommandListView(DatetimeSearchMixin, AdminUserRequiredMixin, ListView):
...
@@ -61,7 +63,43 @@ class CommandListView(DatetimeSearchMixin, AdminUserRequiredMixin, ListView):
return
super
()
.
get_context_data
(
**
kwargs
)
return
super
()
.
get_context_data
(
**
kwargs
)
class
CommandExportView
(
DatetimeSearchMixin
,
AdminUserRequiredMixin
,
View
):
model
=
Command
command
=
user
=
asset
=
system_user
=
action
=
''
date_from
=
date_to
=
None
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
queryset
=
self
.
get_queryset
()
template
=
'terminal/command_report.html'
context
=
{
'queryset'
:
queryset
,
'total_count'
:
len
(
queryset
),
'now'
:
time
.
time
(),
}
content
=
loader
.
render_to_string
(
template
,
context
,
request
)
content_type
=
'application/octet-stream'
response
=
HttpResponse
(
content
,
content_type
)
filename
=
'command-report-{}.html'
.
format
(
int
(
time
.
time
()))
response
[
'Content-Disposition'
]
=
'attachment; filename="
%
s"'
%
filename
return
response
def
get_queryset
(
self
):
self
.
get_date_range
()
self
.
action
=
self
.
request
.
GET
.
get
(
'action'
,
''
)
self
.
command
=
self
.
request
.
GET
.
get
(
'command'
,
''
)
self
.
user
=
self
.
request
.
GET
.
get
(
"user"
,
''
)
self
.
asset
=
self
.
request
.
GET
.
get
(
'asset'
,
''
)
self
.
system_user
=
self
.
request
.
GET
.
get
(
'system_user'
,
''
)
filter_kwargs
=
dict
()
filter_kwargs
[
'date_from'
]
=
self
.
date_from
filter_kwargs
[
'date_to'
]
=
self
.
date_to
if
self
.
user
:
filter_kwargs
[
'user'
]
=
self
.
user
if
self
.
asset
:
filter_kwargs
[
'asset'
]
=
self
.
asset
if
self
.
system_user
:
filter_kwargs
[
'system_user'
]
=
self
.
system_user
if
self
.
command
:
filter_kwargs
[
'input'
]
=
self
.
command
queryset
=
common_storage
.
filter
(
**
filter_kwargs
)
return
queryset
apps/users/api.py
View file @
2ecfecb0
...
@@ -101,7 +101,23 @@ class UserUpdatePKApi(generics.UpdateAPIView):
...
@@ -101,7 +101,23 @@ class UserUpdatePKApi(generics.UpdateAPIView):
user
.
save
()
user
.
save
()
class
UserGroupViewSet
(
BulkModelViewSet
):
class
UserUnblockPKApi
(
generics
.
UpdateAPIView
):
queryset
=
User
.
objects
.
all
()
permission_classes
=
(
IsSuperUser
,)
serializer_class
=
UserSerializer
key_prefix_limit
=
"_LOGIN_LIMIT_{}_{}"
key_prefix_block
=
"_LOGIN_BLOCK_{}"
def
perform_update
(
self
,
serializer
):
user
=
self
.
get_object
()
username
=
user
.
username
if
user
else
''
key_limit
=
self
.
key_prefix_limit
.
format
(
username
,
'*'
)
key_block
=
self
.
key_prefix_block
.
format
(
username
)
cache
.
delete_pattern
(
key_limit
)
cache
.
delete
(
key_block
)
class
UserGroupViewSet
(
IDInFilterMixin
,
BulkModelViewSet
):
queryset
=
UserGroup
.
objects
.
all
()
queryset
=
UserGroup
.
objects
.
all
()
serializer_class
=
UserGroupSerializer
serializer_class
=
UserGroupSerializer
permission_classes
=
(
IsOrgAdmin
,)
permission_classes
=
(
IsOrgAdmin
,)
...
@@ -203,13 +219,15 @@ class UserAuthApi(APIView):
...
@@ -203,13 +219,15 @@ class UserAuthApi(APIView):
permission_classes
=
(
AllowAny
,)
permission_classes
=
(
AllowAny
,)
serializer_class
=
UserSerializer
serializer_class
=
UserSerializer
key_prefix_limit
=
"_LOGIN_LIMIT_{}_{}"
key_prefix_limit
=
"_LOGIN_LIMIT_{}_{}"
key_prefix_block
=
"_LOGIN_BLOCK_{}"
def
post
(
self
,
request
):
def
post
(
self
,
request
):
# limit login
# limit login
username
=
request
.
data
.
get
(
'username'
)
username
=
request
.
data
.
get
(
'username'
)
ip
=
request
.
data
.
get
(
'remote_addr'
,
None
)
ip
=
request
.
data
.
get
(
'remote_addr'
,
None
)
ip
=
ip
if
ip
else
get_login_ip
(
request
)
ip
=
ip
if
ip
else
get_login_ip
(
request
)
key_limit
=
self
.
key_prefix_limit
.
format
(
ip
,
username
)
key_limit
=
self
.
key_prefix_limit
.
format
(
username
,
ip
)
key_block
=
self
.
key_prefix_block
.
format
(
username
)
if
is_block_login
(
key_limit
):
if
is_block_login
(
key_limit
):
msg
=
_
(
"Log in frequently and try again later"
)
msg
=
_
(
"Log in frequently and try again later"
)
return
Response
({
'msg'
:
msg
},
status
=
401
)
return
Response
({
'msg'
:
msg
},
status
=
401
)
...
@@ -224,7 +242,7 @@ class UserAuthApi(APIView):
...
@@ -224,7 +242,7 @@ class UserAuthApi(APIView):
}
}
self
.
write_login_log
(
request
,
data
)
self
.
write_login_log
(
request
,
data
)
set_user_login_failed_count_to_cache
(
key_limit
)
set_user_login_failed_count_to_cache
(
key_limit
,
key_block
)
return
Response
({
'msg'
:
msg
},
status
=
401
)
return
Response
({
'msg'
:
msg
},
status
=
401
)
if
not
user
.
otp_enabled
:
if
not
user
.
otp_enabled
:
...
...
apps/users/templates/users/user_detail.html
View file @
2ecfecb0
...
@@ -182,6 +182,14 @@
...
@@ -182,6 +182,14 @@
</span>
</span>
</td>
</td>
</tr>
</tr>
<tr
style=
"{% if not unblock %}display:none{% endif %}"
>
<td>
{% trans 'Unblock user' %}
</td>
<td>
<span
class=
"pull-right"
>
<button
type=
"button"
class=
"btn btn-primary btn-xs"
id=
"btn-unblock-user"
style=
"width: 54px"
>
{% trans 'Unblock' %}
</button>
</span>
</td>
</tr>
</tbody>
</tbody>
</table>
</table>
</div>
</div>
...
@@ -275,7 +283,7 @@ $(document).ready(function() {
...
@@ -275,7 +283,7 @@ $(document).ready(function() {
.
on
(
'select2:unselect'
,
function
(
evt
)
{
.
on
(
'select2:unselect'
,
function
(
evt
)
{
var
data
=
evt
.
params
.
data
;
var
data
=
evt
.
params
.
data
;
delete
jumpserver
.
nodes_selected
[
data
.
id
];
delete
jumpserver
.
nodes_selected
[
data
.
id
];
})
})
;
})
})
.
on
(
'click'
,
'#is_active'
,
function
()
{
.
on
(
'click'
,
'#is_active'
,
function
()
{
var
the_url
=
"{% url 'api-users:user-detail' pk=user_object.id %}"
;
var
the_url
=
"{% url 'api-users:user-detail' pk=user_object.id %}"
;
...
@@ -293,7 +301,7 @@ $(document).ready(function() {
...
@@ -293,7 +301,7 @@ $(document).ready(function() {
.
on
(
'click'
,
'#force_enable_otp'
,
function
()
{
.
on
(
'click'
,
'#force_enable_otp'
,
function
()
{
{
%
if
request
.
user
==
user_object
%
}
{
%
if
request
.
user
==
user_object
%
}
toastr
.
error
(
"{% trans 'Goto profile page enable MFA' %}"
);
toastr
.
error
(
"{% trans 'Goto profile page enable MFA' %}"
);
return
return
;
{
%
endif
%
}
{
%
endif
%
}
var
the_url
=
"{% url 'api-users:user-detail' pk=user_object.id %}"
;
var
the_url
=
"{% url 'api-users:user-detail' pk=user_object.id %}"
;
...
@@ -426,6 +434,40 @@ $(document).ready(function() {
...
@@ -426,6 +434,40 @@ $(document).ready(function() {
var the_url = '{% url "api-users:user-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', uid);
var the_url = '{% url "api-users:user-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', uid);
var redirect_url = "{% url 'users:user-list' %}";
var redirect_url = "{% url 'users:user-list' %}";
objectDelete($this, name, the_url, redirect_url);
objectDelete($this, name, the_url, redirect_url);
}).on('click', '#btn-unblock-user', function () {
function doReset() {
{#var the_url = '{% url "api-users:user-reset-password" pk=user_object.id %}';#}
var the_url = '{% url "api-users:user-unblock" pk=user_object.id %}';
var body = {};
var success = function() {
var msg = "{% trans "Success" %}";
{#swal("{% trans 'Unblock user' %}", msg, "success");#}
swal({
title: "{% trans 'Unblock user' %}",
text: msg,
type: "success"
}, function() {
location.reload()
}
);
};
APIUpdateAttr({
url: the_url,
body: JSON.stringify(body),
success: success
});
}
swal({
title: "{% trans 'Are you sure?' %}",
text: "{% trans "After unlocking the user, the user can log in normally."%}",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "{% trans 'Confirm' %}",
closeOnConfirm: false
}, function() {
doReset();
});
})
})
</script>
</script>
{% endblock %}
{% endblock %}
apps/users/templates/users/user_list.html
View file @
2ecfecb0
...
@@ -59,7 +59,7 @@ function initTable() {
...
@@ -59,7 +59,7 @@ function initTable() {
ele
:
$
(
'#user_list_table'
),
ele
:
$
(
'#user_list_table'
),
columnDefs
:
[
columnDefs
:
[
{
targets
:
1
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
{
targets
:
1
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
detail_btn
=
'<a href="{% url "users:user-detail" pk=DEFAULT_PK %}">'
+
escape
(
cellData
)
+
'</a>'
;
var
detail_btn
=
'<a href="{% url "users:user-detail" pk=DEFAULT_PK %}">'
+
cellData
+
'</a>'
;
$
(
td
).
html
(
detail_btn
.
replace
(
"{{ DEFAULT_PK }}"
,
rowData
.
id
));
$
(
td
).
html
(
detail_btn
.
replace
(
"{{ DEFAULT_PK }}"
,
rowData
.
id
));
}},
}},
{
targets
:
4
,
createdCell
:
function
(
td
,
cellData
)
{
{
targets
:
4
,
createdCell
:
function
(
td
,
cellData
)
{
...
...
apps/users/urls/api_urls.py
View file @
2ecfecb0
...
@@ -29,6 +29,8 @@ urlpatterns = [
...
@@ -29,6 +29,8 @@ urlpatterns = [
api
.
UserResetPKApi
.
as_view
(),
name
=
'user-public-key-reset'
),
api
.
UserResetPKApi
.
as_view
(),
name
=
'user-public-key-reset'
),
url
(
r'^users/(?P<pk>[0-9a-zA-Z\-]{36})/pubkey/update/$'
,
url
(
r'^users/(?P<pk>[0-9a-zA-Z\-]{36})/pubkey/update/$'
,
api
.
UserUpdatePKApi
.
as_view
(),
name
=
'user-public-key-update'
),
api
.
UserUpdatePKApi
.
as_view
(),
name
=
'user-public-key-update'
),
url
(
r'^users/(?P<pk>[0-9a-zA-Z\-]{36})/unblock/$'
,
api
.
UserUnblockPKApi
.
as_view
(),
name
=
'user-unblock'
),
url
(
r'^users/(?P<pk>[0-9a-zA-Z\-]{36})/groups/$'
,
url
(
r'^users/(?P<pk>[0-9a-zA-Z\-]{36})/groups/$'
,
api
.
UserUpdateGroupApi
.
as_view
(),
name
=
'user-update-group'
),
api
.
UserUpdateGroupApi
.
as_view
(),
name
=
'user-update-group'
),
url
(
r'^groups/(?P<pk>[0-9a-zA-Z\-]{36})/users/$'
,
url
(
r'^groups/(?P<pk>[0-9a-zA-Z\-]{36})/users/$'
,
...
...
apps/users/urls/views_urls.py
View file @
2ecfecb0
...
@@ -8,13 +8,13 @@ app_name = 'users'
...
@@ -8,13 +8,13 @@ app_name = 'users'
urlpatterns
=
[
urlpatterns
=
[
# Login view
# Login view
url
(
r'^login$'
,
views
.
UserLoginView
.
as_view
(),
name
=
'login'
),
url
(
r'^login
/
$'
,
views
.
UserLoginView
.
as_view
(),
name
=
'login'
),
url
(
r'^logout$'
,
views
.
UserLogoutView
.
as_view
(),
name
=
'logout'
),
url
(
r'^logout
/
$'
,
views
.
UserLogoutView
.
as_view
(),
name
=
'logout'
),
url
(
r'^login/otp$'
,
views
.
UserLoginOtpView
.
as_view
(),
name
=
'login-otp'
),
url
(
r'^login/otp
/
$'
,
views
.
UserLoginOtpView
.
as_view
(),
name
=
'login-otp'
),
url
(
r'^password/forgot$'
,
views
.
UserForgotPasswordView
.
as_view
(),
name
=
'forgot-password'
),
url
(
r'^password/forgot
/
$'
,
views
.
UserForgotPasswordView
.
as_view
(),
name
=
'forgot-password'
),
url
(
r'^password/forgot/sendmail-success$'
,
views
.
UserForgotPasswordSendmailSuccessView
.
as_view
(),
name
=
'forgot-password-sendmail-success'
),
url
(
r'^password/forgot/sendmail-success
/
$'
,
views
.
UserForgotPasswordSendmailSuccessView
.
as_view
(),
name
=
'forgot-password-sendmail-success'
),
url
(
r'^password/reset$'
,
views
.
UserResetPasswordView
.
as_view
(),
name
=
'reset-password'
),
url
(
r'^password/reset
/
$'
,
views
.
UserResetPasswordView
.
as_view
(),
name
=
'reset-password'
),
url
(
r'^password/reset/success$'
,
views
.
UserResetPasswordSuccessView
.
as_view
(),
name
=
'reset-password-success'
),
url
(
r'^password/reset/success
/
$'
,
views
.
UserResetPasswordSuccessView
.
as_view
(),
name
=
'reset-password-success'
),
# Profile
# Profile
url
(
r'^profile/$'
,
views
.
UserProfileView
.
as_view
(),
name
=
'user-profile'
),
url
(
r'^profile/$'
,
views
.
UserProfileView
.
as_view
(),
name
=
'user-profile'
),
...
@@ -29,23 +29,23 @@ urlpatterns = [
...
@@ -29,23 +29,23 @@ urlpatterns = [
url
(
r'^profile/otp/settings-success/$'
,
views
.
UserOtpSettingsSuccessView
.
as_view
(),
name
=
'user-otp-settings-success'
),
url
(
r'^profile/otp/settings-success/$'
,
views
.
UserOtpSettingsSuccessView
.
as_view
(),
name
=
'user-otp-settings-success'
),
# User view
# User view
url
(
r'^user$'
,
views
.
UserListView
.
as_view
(),
name
=
'user-list'
),
url
(
r'^user
/
$'
,
views
.
UserListView
.
as_view
(),
name
=
'user-list'
),
url
(
r'^user/export/'
,
views
.
UserExportView
.
as_view
(),
name
=
'user-export'
),
url
(
r'^user/export/
$
'
,
views
.
UserExportView
.
as_view
(),
name
=
'user-export'
),
url
(
r'^first-login/$'
,
views
.
UserFirstLoginView
.
as_view
(),
name
=
'user-first-login'
),
url
(
r'^first-login/$'
,
views
.
UserFirstLoginView
.
as_view
(),
name
=
'user-first-login'
),
url
(
r'^user/import/$'
,
views
.
UserBulkImportView
.
as_view
(),
name
=
'user-import'
),
url
(
r'^user/import/$'
,
views
.
UserBulkImportView
.
as_view
(),
name
=
'user-import'
),
url
(
r'^user/create$'
,
views
.
UserCreateView
.
as_view
(),
name
=
'user-create'
),
url
(
r'^user/create
/
$'
,
views
.
UserCreateView
.
as_view
(),
name
=
'user-create'
),
url
(
r'^user/(?P<pk>[0-9a-zA-Z\-]{36})/update$'
,
views
.
UserUpdateView
.
as_view
(),
name
=
'user-update'
),
url
(
r'^user/(?P<pk>[0-9a-zA-Z\-]{36})/update
/
$'
,
views
.
UserUpdateView
.
as_view
(),
name
=
'user-update'
),
url
(
r'^user/update$'
,
views
.
UserBulkUpdateView
.
as_view
(),
name
=
'user-bulk-update'
),
url
(
r'^user/update
/
$'
,
views
.
UserBulkUpdateView
.
as_view
(),
name
=
'user-bulk-update'
),
url
(
r'^user/(?P<pk>[0-9a-zA-Z\-]{36})$'
,
views
.
UserDetailView
.
as_view
(),
name
=
'user-detail'
),
url
(
r'^user/(?P<pk>[0-9a-zA-Z\-]{36})
/
$'
,
views
.
UserDetailView
.
as_view
(),
name
=
'user-detail'
),
url
(
r'^user/(?P<pk>[0-9a-zA-Z\-]{36})/assets'
,
views
.
UserGrantedAssetView
.
as_view
(),
name
=
'user-granted-asset'
),
url
(
r'^user/(?P<pk>[0-9a-zA-Z\-]{36})/assets
/$
'
,
views
.
UserGrantedAssetView
.
as_view
(),
name
=
'user-granted-asset'
),
url
(
r'^user/(?P<pk>[0-9a-zA-Z\-]{36})/login-history'
,
views
.
UserDetailView
.
as_view
(),
name
=
'user-login-history'
),
url
(
r'^user/(?P<pk>[0-9a-zA-Z\-]{36})/login-history
/$
'
,
views
.
UserDetailView
.
as_view
(),
name
=
'user-login-history'
),
# User group view
# User group view
url
(
r'^user-group$'
,
views
.
UserGroupListView
.
as_view
(),
name
=
'user-group-list'
),
url
(
r'^user-group
/
$'
,
views
.
UserGroupListView
.
as_view
(),
name
=
'user-group-list'
),
url
(
r'^user-group/(?P<pk>[0-9a-zA-Z\-]{36})$'
,
views
.
UserGroupDetailView
.
as_view
(),
name
=
'user-group-detail'
),
url
(
r'^user-group/(?P<pk>[0-9a-zA-Z\-]{36})
/
$'
,
views
.
UserGroupDetailView
.
as_view
(),
name
=
'user-group-detail'
),
url
(
r'^user-group/create$'
,
views
.
UserGroupCreateView
.
as_view
(),
name
=
'user-group-create'
),
url
(
r'^user-group/create
/
$'
,
views
.
UserGroupCreateView
.
as_view
(),
name
=
'user-group-create'
),
url
(
r'^user-group/(?P<pk>[0-9a-zA-Z\-]{36})/update$'
,
views
.
UserGroupUpdateView
.
as_view
(),
name
=
'user-group-update'
),
url
(
r'^user-group/(?P<pk>[0-9a-zA-Z\-]{36})/update
/
$'
,
views
.
UserGroupUpdateView
.
as_view
(),
name
=
'user-group-update'
),
url
(
r'^user-group/(?P<pk>[0-9a-zA-Z\-]{36})/assets'
,
views
.
UserGroupGrantedAssetView
.
as_view
(),
name
=
'user-group-granted-asset'
),
url
(
r'^user-group/(?P<pk>[0-9a-zA-Z\-]{36})/assets
/$
'
,
views
.
UserGroupGrantedAssetView
.
as_view
(),
name
=
'user-group-granted-asset'
),
# Login log
# Login log
url
(
r'^login-log/$'
,
views
.
LoginLogListView
.
as_view
(),
name
=
'login-log-list'
),
url
(
r'^login-log/$'
,
views
.
LoginLogListView
.
as_view
(),
name
=
'login-log-list'
),
...
...
apps/users/utils.py
View file @
2ecfecb0
...
@@ -212,10 +212,10 @@ def write_login_log(*args, **kwargs):
...
@@ -212,10 +212,10 @@ def write_login_log(*args, **kwargs):
def
get_ip_city
(
ip
,
timeout
=
10
):
def
get_ip_city
(
ip
,
timeout
=
10
):
# Taobao ip api: http://ip.taobao.com/
/
service/getIpInfo.php?ip=8.8.8.8
# Taobao ip api: http://ip.taobao.com/service/getIpInfo.php?ip=8.8.8.8
# Sina ip api: http://int.dpool.sina.com.cn/iplookup/iplookup.php?ip=8.8.8.8&format=json
# Sina ip api: http://int.dpool.sina.com.cn/iplookup/iplookup.php?ip=8.8.8.8&format=json
url
=
'http://i
nt.dpool.sina.com.cn/iplookup/iplookup.php?ip=
%
s&format=json
'
%
ip
url
=
'http://i
p.taobao.com/service/getIpInfo.php?ip=
%
s
'
%
ip
try
:
try
:
r
=
requests
.
get
(
url
,
timeout
=
timeout
)
r
=
requests
.
get
(
url
,
timeout
=
timeout
)
except
:
except
:
...
@@ -224,8 +224,8 @@ def get_ip_city(ip, timeout=10):
...
@@ -224,8 +224,8 @@ def get_ip_city(ip, timeout=10):
if
r
and
r
.
status_code
==
200
:
if
r
and
r
.
status_code
==
200
:
try
:
try
:
data
=
r
.
json
()
data
=
r
.
json
()
if
not
isinstance
(
data
,
int
)
and
data
[
'
ret'
]
==
1
:
if
not
isinstance
(
data
,
int
)
and
data
[
'
code'
]
==
0
:
city
=
data
[
'
country'
]
+
' '
+
data
[
'city'
]
city
=
data
[
'
data'
][
'country'
]
+
' '
+
data
[
'data'
]
[
'city'
]
except
ValueError
:
except
ValueError
:
pass
pass
return
city
return
city
...
@@ -333,7 +333,7 @@ def check_password_rules(password):
...
@@ -333,7 +333,7 @@ def check_password_rules(password):
return
bool
(
match_obj
)
return
bool
(
match_obj
)
def
set_user_login_failed_count_to_cache
(
key_limit
):
def
set_user_login_failed_count_to_cache
(
key_limit
,
key_block
):
count
=
cache
.
get
(
key_limit
)
count
=
cache
.
get
(
key_limit
)
count
=
count
+
1
if
count
else
1
count
=
count
+
1
if
count
else
1
...
@@ -343,6 +343,15 @@ def set_user_login_failed_count_to_cache(key_limit):
...
@@ -343,6 +343,15 @@ def set_user_login_failed_count_to_cache(key_limit):
limit_time
=
setting_limit_time
.
cleaned_value
if
setting_limit_time
\
limit_time
=
setting_limit_time
.
cleaned_value
if
setting_limit_time
\
else
settings
.
DEFAULT_LOGIN_LIMIT_TIME
else
settings
.
DEFAULT_LOGIN_LIMIT_TIME
setting_limit_count
=
Setting
.
objects
.
filter
(
name
=
'SECURITY_LOGIN_LIMIT_COUNT'
)
.
first
()
limit_count
=
setting_limit_count
.
cleaned_value
if
setting_limit_count
\
else
settings
.
DEFAULT_LOGIN_LIMIT_COUNT
if
count
>=
limit_count
:
cache
.
set
(
key_block
,
1
,
int
(
limit_time
)
*
60
)
cache
.
set
(
key_limit
,
count
,
int
(
limit_time
)
*
60
)
cache
.
set
(
key_limit
,
count
,
int
(
limit_time
)
*
60
)
...
@@ -357,3 +366,9 @@ def is_block_login(key_limit):
...
@@ -357,3 +366,9 @@ def is_block_login(key_limit):
if
count
and
count
>=
limit_count
:
if
count
and
count
>=
limit_count
:
return
True
return
True
def
is_need_unblock
(
key_block
):
if
not
cache
.
get
(
key_block
):
return
False
return
True
apps/users/views/login.py
View file @
2ecfecb0
...
@@ -52,6 +52,7 @@ class UserLoginView(FormView):
...
@@ -52,6 +52,7 @@ class UserLoginView(FormView):
redirect_field_name
=
'next'
redirect_field_name
=
'next'
key_prefix_captcha
=
"_LOGIN_INVALID_{}"
key_prefix_captcha
=
"_LOGIN_INVALID_{}"
key_prefix_limit
=
"_LOGIN_LIMIT_{}_{}"
key_prefix_limit
=
"_LOGIN_LIMIT_{}_{}"
key_prefix_block
=
"_LOGIN_BLOCK_{}"
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
if
request
.
user
.
is_staff
:
if
request
.
user
.
is_staff
:
...
@@ -65,7 +66,7 @@ class UserLoginView(FormView):
...
@@ -65,7 +66,7 @@ class UserLoginView(FormView):
# limit login authentication
# limit login authentication
ip
=
get_login_ip
(
request
)
ip
=
get_login_ip
(
request
)
username
=
self
.
request
.
POST
.
get
(
'username'
)
username
=
self
.
request
.
POST
.
get
(
'username'
)
key_limit
=
self
.
key_prefix_limit
.
format
(
ip
,
username
)
key_limit
=
self
.
key_prefix_limit
.
format
(
username
,
ip
)
if
is_block_login
(
key_limit
):
if
is_block_login
(
key_limit
):
return
self
.
render_to_response
(
self
.
get_context_data
(
block_login
=
True
))
return
self
.
render_to_response
(
self
.
get_context_data
(
block_login
=
True
))
...
@@ -91,8 +92,9 @@ class UserLoginView(FormView):
...
@@ -91,8 +92,9 @@ class UserLoginView(FormView):
# limit user login failed count
# limit user login failed count
ip
=
get_login_ip
(
self
.
request
)
ip
=
get_login_ip
(
self
.
request
)
key_limit
=
self
.
key_prefix_limit
.
format
(
ip
,
username
)
key_limit
=
self
.
key_prefix_limit
.
format
(
username
,
ip
)
set_user_login_failed_count_to_cache
(
key_limit
)
key_block
=
self
.
key_prefix_block
.
format
(
username
)
set_user_login_failed_count_to_cache
(
key_limit
,
key_block
)
# show captcha
# show captcha
cache
.
set
(
self
.
key_prefix_captcha
.
format
(
ip
),
1
,
3600
)
cache
.
set
(
self
.
key_prefix_captcha
.
format
(
ip
),
1
,
3600
)
...
...
apps/users/views/user.py
View file @
2ecfecb0
...
@@ -37,7 +37,9 @@ from common.models import Setting
...
@@ -37,7 +37,9 @@ from common.models import Setting
from
common.permissions
import
AdminUserRequiredMixin
from
common.permissions
import
AdminUserRequiredMixin
from
..
import
forms
from
..
import
forms
from
..models
import
User
,
UserGroup
from
..models
import
User
,
UserGroup
from
..utils
import
generate_otp_uri
,
check_otp_code
,
get_user_or_tmp_user
,
get_password_check_rules
,
check_password_rules
from
..utils
import
generate_otp_uri
,
check_otp_code
,
\
get_user_or_tmp_user
,
get_password_check_rules
,
check_password_rules
,
\
is_need_unblock
from
..signals
import
post_user_create
from
..signals
import
post_user_create
from
..tasks
import
write_login_log_async
from
..tasks
import
write_login_log_async
...
@@ -169,13 +171,17 @@ class UserDetailView(AdminUserRequiredMixin, DetailView):
...
@@ -169,13 +171,17 @@ class UserDetailView(AdminUserRequiredMixin, DetailView):
model
=
User
model
=
User
template_name
=
'users/user_detail.html'
template_name
=
'users/user_detail.html'
context_object_name
=
"user_object"
context_object_name
=
"user_object"
key_prefix_block
=
"_LOGIN_BLOCK_{}"
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
user
=
self
.
get_object
()
key_block
=
self
.
key_prefix_block
.
format
(
user
.
username
)
groups
=
UserGroup
.
objects
.
exclude
(
id__in
=
self
.
object
.
groups
.
all
())
groups
=
UserGroup
.
objects
.
exclude
(
id__in
=
self
.
object
.
groups
.
all
())
context
=
{
context
=
{
'app'
:
_
(
'Users'
),
'app'
:
_
(
'Users'
),
'action'
:
_
(
'User detail'
),
'action'
:
_
(
'User detail'
),
'groups'
:
groups
'groups'
:
groups
,
'unblock'
:
is_need_unblock
(
key_block
),
}
}
kwargs
.
update
(
context
)
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
return
super
()
.
get_context_data
(
**
kwargs
)
...
...
docs/step_by_step.rst
View file @
2ecfecb0
...
@@ -228,7 +228,7 @@ Luna 已改为纯前端,需要 Nginx 来运行访问
...
@@ -228,7 +228,7 @@ Luna 已改为纯前端,需要 Nginx 来运行访问
-p 8081:8080 -v /opt/guacamole/key:/config/guacamole/key \
-p 8081:8080 -v /opt/guacamole/key:/config/guacamole/key \
-e JUMPSERVER_KEY_DIR=/config/guacamole/key \
-e JUMPSERVER_KEY_DIR=/config/guacamole/key \
-e JUMPSERVER_SERVER=http://<填写本机的IP地址>:8080 \
-e JUMPSERVER_SERVER=http://<填写本机的IP地址>:8080 \
registry.jumpserver.org/public/guacamole:
1.0.0
registry.jumpserver.org/public/guacamole:
latest
这里所需要注意的是 guacamole 暴露出来的端口是 8081,若与主机上其他端口冲突请自定义一下。
这里所需要注意的是 guacamole 暴露出来的端口是 8081,若与主机上其他端口冲突请自定义一下。
...
...
jms
View file @
2ecfecb0
...
@@ -122,8 +122,8 @@ def start_gunicorn():
...
@@ -122,8 +122,8 @@ def start_gunicorn():
cmd
=
[
cmd
=
[
'gunicorn'
,
'jumpserver.wsgi'
,
'gunicorn'
,
'jumpserver.wsgi'
,
'-b'
,
bind
,
'-b'
,
bind
,
'-w'
,
str
(
WORKERS
),
'-k'
,
'eventlet'
,
'-k'
,
'eventlet'
,
'-w'
,
str
(
WORKERS
),
'--access-logformat'
,
log_format
,
'--access-logformat'
,
log_format
,
'-p'
,
pid_file
,
'-p'
,
pid_file
,
]
]
...
...
requirements/requirements.txt
View file @
2ecfecb0
...
@@ -48,7 +48,7 @@ MarkupSafe==1.0
...
@@ -48,7 +48,7 @@ MarkupSafe==1.0
mysqlclient==1.3.12
mysqlclient==1.3.12
olefile==0.44
olefile==0.44
openapi-codec==1.3.2
openapi-codec==1.3.2
paramiko==2.4.
0
paramiko==2.4.
1
passlib==1.7.1
passlib==1.7.1
Pillow==4.3.0
Pillow==4.3.0
pyasn1==0.4.2
pyasn1==0.4.2
...
...
utils/make_migrations.sh
View file @
2ecfecb0
...
@@ -5,4 +5,4 @@ python3 ../apps/manage.py makemigrations
...
@@ -5,4 +5,4 @@ python3 ../apps/manage.py makemigrations
python3 ../apps/manage.py migrate
python3 ../apps/manage.py migrate
python3 ../apps/manage.py makemigrations
–
-merge
python3 ../apps/manage.py makemigrations
-
-merge
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment