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
4efad4e5
Commit
4efad4e5
authored
Aug 14, 2019
by
BaiJiangJie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Feature] 会话管理: Session 页面展示;Command 待续
parent
1e49de79
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
526 additions
and
78 deletions
+526
-78
asset_detail.html
apps/assets/templates/assets/asset_detail.html
+1
-1
jumpserver.js
apps/static/js/jumpserver.js
+1
-1
_nav.html
apps/templates/_nav.html
+16
-3
command.py
apps/terminal/api/command.py
+70
-29
session.py
apps/terminal/api/session.py
+2
-1
task.py
apps/terminal/api/task.py
+3
-1
__init__.py
apps/terminal/backends/__init__.py
+3
-1
models.py
apps/terminal/backends/command/models.py
+25
-6
serializers.py
apps/terminal/backends/command/serializers.py
+16
-6
session.py
apps/terminal/models/session.py
+3
-0
v1.py
apps/terminal/serializers/v1.py
+1
-1
asset_command_list.html
apps/terminal/templates/terminal/asset_command_list.html
+0
-0
asset_command_report.html
apps/terminal/templates/terminal/asset_command_report.html
+0
-0
asset_session_detail.html
apps/terminal/templates/terminal/asset_session_detail.html
+0
-0
asset_session_list.html
apps/terminal/templates/terminal/asset_session_list.html
+0
-0
database_command_list.html
apps/terminal/templates/terminal/database_command_list.html
+0
-0
database_session_detail.html
.../terminal/templates/terminal/database_session_detail.html
+11
-0
database_session_list.html
apps/terminal/templates/terminal/database_session_list.html
+258
-0
views_urls.py
apps/terminal/urls/views_urls.py
+11
-5
__init__.py
apps/terminal/views/__init__.py
+3
-2
asset_command.py
apps/terminal/views/asset_command.py
+1
-1
asset_session.py
apps/terminal/views/asset_session.py
+5
-20
base_session.py
apps/terminal/views/base_session.py
+27
-0
database_session.py
apps/terminal/views/database_session.py
+69
-0
No files found.
apps/assets/templates/assets/asset_detail.html
View file @
4efad4e5
...
...
@@ -126,7 +126,7 @@
</tr>
<tr>
<td>
{% trans 'Date joined' %}:
</td>
<td><b>
{{ asset.date_
join
ed|date:"Y-m-j H:i:s" }}
</b></td>
<td><b>
{{ asset.date_
creat
ed|date:"Y-m-j H:i:s" }}
</b></td>
</tr>
<tr>
<td>
{% trans 'Comment' %}:
</td>
...
...
apps/static/js/jumpserver.js
View file @
4efad4e5
...
...
@@ -146,7 +146,7 @@ function activeNav() {
if
(
app
===
''
){
$
(
'#index'
).
addClass
(
'active'
);
}
else
if
(
app
===
'xpack'
&&
resource
===
'cloud'
)
{
else
if
(
(
app
===
'xpack'
&&
resource
===
'cloud'
)
||
(
app
===
'terminal'
&&
(
resource
===
'asset'
||
resource
===
'database'
))
)
{
var
item
=
url_array
[
3
];
$
(
"#"
+
app
).
addClass
(
'active'
);
$
(
'#'
+
app
+
' #'
+
resource
).
addClass
(
'active'
);
...
...
apps/templates/_nav.html
View file @
4efad4e5
...
...
@@ -59,9 +59,22 @@
<i
class=
"fa fa-rocket"
style=
"width: 14px"
></i>
<span
class=
"nav-label"
>
{% trans 'Sessions' %}
</span><span
class=
"fa arrow"
></span>
</a>
<ul
class=
"nav nav-second-level"
>
<li
id=
"session-online"
><a
href=
"{% url 'terminal:session-online-list' %}"
>
{% trans 'Session online' %}
</a></li>
<li
id=
"session-offline"
><a
href=
"{% url 'terminal:session-offline-list' %}"
>
{% trans 'Session offline' %}
</a></li>
<li
id=
"command"
><a
href=
"{% url 'terminal:command-list' %}"
>
{% trans 'Commands' %}
</a></li>
<li
id=
"asset"
>
<a
href=
"#"
><span
class=
"nav-label"
>
{% trans 'Asset sessions' %}
</span><span
class=
"fa arrow"
></span></a>
<ul
class=
"nav nav-third-level"
>
<li
id=
"session-online"
><a
href=
"{% url 'terminal:session-online-list' %}"
>
{% trans 'Session online' %}
</a></li>
<li
id=
"session-offline"
><a
href=
"{% url 'terminal:session-offline-list' %}"
>
{% trans 'Session offline' %}
</a></li>
<li
id=
"command"
><a
href=
"{% url 'terminal:command-list' %}"
>
{% trans 'Commands' %}
</a></li>
</ul>
</li>
<li
id=
"database"
>
<a
href=
"#"
><span
class=
"nav-label"
>
{% trans 'Database sessions' %}
</span><span
class=
"fa arrow"
></span></a>
<ul
class=
"nav nav-third-level"
>
<li
id=
"session-online"
><a
href=
"{% url 'terminal:database-session-online-list' %}"
>
{% trans 'Session online' %}
</a></li>
<li
id=
"session-offline"
><a
href=
"{% url 'terminal:database-session-offline-list' %}"
>
{% trans 'Session offline' %}
</a></li>
{#
<li
id=
"command"
><a
href=
"{% url 'terminal:command-list' %}"
>
{% trans 'Commands' %}
</a></li>
#}
</ul>
</li>
<li>
<a
href=
"{% url 'terminal:web-terminal' %}"
target=
"_blank"
>
<span
class=
"nav-label"
>
{% trans 'Web terminal' %}
</span>
...
...
apps/terminal/api/command.py
View file @
4efad4e5
...
...
@@ -14,33 +14,19 @@ from common.permissions import IsOrgAdminOrAppUser, IsAuditor
from
common.utils
import
get_logger
from
..backends
import
(
get_command_storage
,
get_multi_command_storage
,
SessionCommandSerializer
,
SessionCommandSerializer
,
DatabaseSessionCommandSerializer
)
logger
=
get_logger
(
__name__
)
__all__
=
[
'CommandViewSet'
,
'CommandExportApi'
]
__all__
=
[
'CommandViewSet'
,
'CommandExportApi'
,
'DatabaseCommandViewSet'
]
class
CommandQueryMixin
:
class
Base
CommandQueryMixin
:
command_store
=
get_command_storage
()
pagination_class
=
LimitOffsetPagination
permission_classes
=
[
IsOrgAdminOrAppUser
|
IsAuditor
]
filter_fields
=
[
"asset"
,
"system_user"
,
"user"
,
"session"
,
]
default_days_ago
=
5
def
get_queryset
(
self
):
date_from
,
date_to
=
self
.
get_date_range
()
q
=
self
.
request
.
query_params
multi_command_storage
=
get_multi_command_storage
()
queryset
=
multi_command_storage
.
filter
(
date_from
=
date_from
,
date_to
=
date_to
,
input
=
q
.
get
(
"input"
),
user
=
q
.
get
(
"user"
),
asset
=
q
.
get
(
"asset"
),
system_user
=
q
.
get
(
"system_user"
)
)
return
queryset
def
filter_queryset
(
self
,
queryset
):
return
queryset
...
...
@@ -60,21 +46,49 @@ class CommandQueryMixin:
return
float
(
date_from_st
),
float
(
date_to_st
)
class
CommandViewSet
(
CommandQueryMixin
,
viewsets
.
ModelViewSet
):
"""接受app发送来的command log, 格式如下
{
"user": "admin",
"asset": "localhost",
"system_user": "web",
"session": "xxxxxx",
"input": "whoami",
"output": "d2hvbWFp", # base64.b64encode(s)
"timestamp": 1485238673.0
}
class
CommandQueryMixin
(
BaseCommandQueryMixin
):
"""
Asset Command Query Mixin
"""
filter_fields
=
[
"user"
,
"asset"
,
"system_user"
,
"session"
,
]
def
get_queryset
(
self
):
date_from
,
date_to
=
self
.
get_date_range
()
q
=
self
.
request
.
query_params
multi_command_storage
=
get_multi_command_storage
()
queryset
=
multi_command_storage
.
filter
(
date_from
=
date_from
,
date_to
=
date_to
,
input
=
q
.
get
(
"input"
),
user
=
q
.
get
(
"user"
),
asset
=
q
.
get
(
"asset"
),
system_user
=
q
.
get
(
"system_user"
)
)
return
queryset
class
DatabaseCommandQueryMixin
(
BaseCommandQueryMixin
):
"""
Database Command Query Mixin
"""
filter_fields
=
[
"user"
,
"database"
,
"db_host"
,
"db_name"
,
"db_user"
]
def
get_queryset
(
self
):
date_from
,
date_to
=
self
.
get_date_range
()
q
=
self
.
request
.
query_params
multi_command_storage
=
get_multi_command_storage
()
queryset
=
multi_command_storage
.
filter
(
date_from
=
date_from
,
date_to
=
date_to
,
input
=
q
.
get
(
"input"
),
user
=
q
.
get
(
"user"
),
database
=
q
.
get
(
"database"
),
db_host
=
q
.
get
(
"db_host"
),
db_name
=
q
.
get
(
"db_name"
),
db_user
=
q
.
get
(
"db_user"
)
)
return
queryset
class
BaseCommandViewSet
(
viewsets
.
ModelViewSet
):
command_store
=
get_command_storage
()
serializer_class
=
SessionCommandSerializer
def
create
(
self
,
request
,
*
args
,
**
kwargs
):
serializer
=
self
.
serializer_class
(
data
=
request
.
data
,
many
=
True
)
...
...
@@ -90,6 +104,31 @@ class CommandViewSet(CommandQueryMixin, viewsets.ModelViewSet):
return
Response
({
"msg"
:
msg
},
status
=
401
)
class
CommandViewSet
(
CommandQueryMixin
,
BaseCommandViewSet
):
"""
Asset Command ViewSet
接受app发送来的command log, 格式如下
{
"user": "admin",
"asset": "localhost",
"system_user": "web",
"session": "xxxxxx",
"input": "whoami",
"output": "d2hvbWFp", # base64.b64encode(s)
"timestamp": 1485238673.0
}
"""
serializer_class
=
SessionCommandSerializer
class
DatabaseCommandViewSet
(
DatabaseCommandQueryMixin
,
BaseCommandViewSet
):
"""
Database Command ViewSet
"""
serializer_class
=
DatabaseSessionCommandSerializer
class
CommandExportApi
(
CommandQueryMixin
,
generics
.
ListAPIView
):
serializer_class
=
SessionCommandSerializer
...
...
@@ -108,3 +147,5 @@ class CommandExportApi(CommandQueryMixin, generics.ListAPIView):
filename
=
'command-report-{}.html'
.
format
(
int
(
time
.
time
()))
response
[
'Content-Disposition'
]
=
'attachment; filename="
%
s"'
%
filename
return
response
apps/terminal/api/session.py
View file @
4efad4e5
...
...
@@ -68,7 +68,8 @@ class DatabaseSessionViewSet(OrgBulkModelViewSet):
pagination_class
=
LimitOffsetPagination
permission_classes
=
(
IsOrgAdminOrAppUser
|
IsAuditor
,
)
filter_fields
=
[
'user'
,
'database'
,
'db_host'
,
'db_name'
,
'db_user'
'user'
,
'database'
,
'db_host'
,
'db_name'
,
'db_user'
,
'is_finished'
,
'terminal'
,
'remote_addr'
]
date_range_filter_fields
=
[
(
'date_start'
,
(
'date_from'
,
'date_to'
))
...
...
apps/terminal/api/task.py
View file @
4efad4e5
...
...
@@ -6,7 +6,7 @@ from rest_framework_bulk import BulkModelViewSet
from
common.utils
import
get_object_or_none
from
common.permissions
import
IsOrgAdminOrAppUser
from
..models
import
Session
,
Task
from
..models
import
Session
,
Task
,
DatabaseSession
from
..
import
serializers
...
...
@@ -28,6 +28,8 @@ class KillSessionAPI(APIView):
validated_session
=
[]
for
session_id
in
request
.
data
:
session
=
get_object_or_none
(
Session
,
id
=
session_id
)
if
not
session
:
session
=
get_object_or_none
(
DatabaseSession
,
id
=
session_id
)
if
session
and
not
session
.
is_finished
:
validated_session
.
append
(
session_id
)
self
.
model
.
objects
.
create
(
...
...
apps/terminal/backends/__init__.py
View file @
4efad4e5
from
importlib
import
import_module
from
django.conf
import
settings
from
.command.serializers
import
SessionCommandSerializer
from
.command.serializers
import
(
SessionCommandSerializer
,
DatabaseSessionCommandSerializer
)
from
common
import
utils
...
...
apps/terminal/backends/command/models.py
View file @
4efad4e5
...
...
@@ -7,19 +7,14 @@ from django.utils.translation import ugettext_lazy as _
from
orgs.mixins
import
OrgModelMixin
class
AbstractSessionCommand
(
OrgModelMixin
):
class
Base
AbstractSessionCommand
(
OrgModelMixin
):
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
user
=
models
.
CharField
(
max_length
=
64
,
db_index
=
True
,
verbose_name
=
_
(
"User"
))
asset
=
models
.
CharField
(
max_length
=
128
,
db_index
=
True
,
verbose_name
=
_
(
"Asset"
))
system_user
=
models
.
CharField
(
max_length
=
64
,
db_index
=
True
,
verbose_name
=
_
(
"System user"
))
input
=
models
.
CharField
(
max_length
=
128
,
db_index
=
True
,
verbose_name
=
_
(
"Input"
))
output
=
models
.
CharField
(
max_length
=
1024
,
blank
=
True
,
verbose_name
=
_
(
"Output"
))
session
=
models
.
CharField
(
max_length
=
36
,
db_index
=
True
,
verbose_name
=
_
(
"Session"
))
timestamp
=
models
.
IntegerField
(
db_index
=
True
)
class
Meta
:
abstract
=
True
@classmethod
def
from_dict
(
cls
,
d
):
self
=
cls
()
...
...
@@ -43,3 +38,27 @@ class AbstractSessionCommand(OrgModelMixin):
def
__str__
(
self
):
return
self
.
input
class
Meta
:
abstract
=
True
class
AbstractSessionCommand
(
BaseAbstractSessionCommand
):
asset
=
models
.
CharField
(
max_length
=
128
,
db_index
=
True
,
verbose_name
=
_
(
"Asset"
))
system_user
=
models
.
CharField
(
max_length
=
64
,
db_index
=
True
,
verbose_name
=
_
(
"System user"
))
class
Meta
:
abstract
=
True
class
AbstractDatabaseSessionCommand
(
BaseAbstractSessionCommand
):
user_id
=
models
.
CharField
(
max_length
=
36
,
db_index
=
True
,
verbose_name
=
_
(
"User ID"
))
database
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
'Database'
))
database_id
=
models
.
CharField
(
max_length
=
36
,
db_index
=
True
,
verbose_name
=
_
(
"Database ID"
))
db_host
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
'Database host'
))
db_name
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Database name'
))
db_user
=
models
.
CharField
(
max_length
=
32
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Database user'
))
class
Meta
:
abstract
=
True
apps/terminal/backends/command/serializers.py
View file @
4efad4e5
...
...
@@ -2,16 +2,26 @@
from
rest_framework
import
serializers
class
SessionCommandSerializer
(
serializers
.
Serializer
):
"""使用这个类作为基础Command Log Serializer类, 用来序列化"""
class
BaseSessionCommandSerializer
(
serializers
.
Serializer
):
id
=
serializers
.
UUIDField
(
read_only
=
True
)
user
=
serializers
.
CharField
(
max_length
=
64
)
asset
=
serializers
.
CharField
(
max_length
=
128
)
system_user
=
serializers
.
CharField
(
max_length
=
64
)
input
=
serializers
.
CharField
(
max_length
=
128
)
output
=
serializers
.
CharField
(
max_length
=
1024
,
allow_blank
=
True
)
session
=
serializers
.
CharField
(
max_length
=
36
)
org_id
=
serializers
.
CharField
(
max_length
=
36
,
required
=
False
,
default
=
''
,
allow_null
=
True
,
allow_blank
=
True
)
timestamp
=
serializers
.
IntegerField
()
class
SessionCommandSerializer
(
BaseSessionCommandSerializer
):
"""使用这个类作为基础Command Log Serializer类, 用来序列化"""
user
=
serializers
.
CharField
(
max_length
=
64
)
asset
=
serializers
.
CharField
(
max_length
=
128
)
system_user
=
serializers
.
CharField
(
max_length
=
64
)
class
DatabaseSessionCommandSerializer
(
BaseSessionCommandSerializer
):
user_id
=
serializers
.
CharField
(
max_length
=
36
)
database
=
serializers
.
CharField
(
max_length
=
128
)
database_id
=
serializers
.
CharField
(
max_length
=
36
)
db_host
=
serializers
.
CharField
(
max_length
=
128
)
db_name
=
serializers
.
CharField
(
max_length
=
128
)
db_user
=
serializers
.
CharField
(
max_length
=
32
)
apps/terminal/models/session.py
View file @
4efad4e5
...
...
@@ -71,6 +71,9 @@ class DatabaseSession(BaseSession):
db_name
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Database name'
))
db_user
=
models
.
CharField
(
max_length
=
32
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Database user'
))
def
can_replay
(
self
):
return
self
.
has_replay
class
Meta
:
db_table
=
"terminal_database_session"
ordering
=
[
"-date_start"
]
apps/terminal/serializers/v1.py
View file @
4efad4e5
...
...
@@ -50,7 +50,7 @@ class DatabaseSessionSerializer(BulkOrgResourceModelSerializer):
fields
=
[
'id'
,
'user'
,
'database'
,
'db_host'
,
'db_name'
,
'db_user'
,
'login_from_display'
,
'remote_addr'
,
'is_finished'
,
'has_replay'
,
'date_start'
,
'date_end'
,
'terminal'
,
'command_amount'
'
can_replay'
,
'
date_start'
,
'date_end'
,
'terminal'
,
'command_amount'
]
...
...
apps/terminal/templates/terminal/command_list.html
→
apps/terminal/templates/terminal/
asset_
command_list.html
View file @
4efad4e5
File moved
apps/terminal/templates/terminal/command_report.html
→
apps/terminal/templates/terminal/
asset_
command_report.html
View file @
4efad4e5
File moved
apps/terminal/templates/terminal/session_detail.html
→
apps/terminal/templates/terminal/
asset_
session_detail.html
View file @
4efad4e5
File moved
apps/terminal/templates/terminal/session_list.html
→
apps/terminal/templates/terminal/
asset_
session_list.html
View file @
4efad4e5
File moved
apps/terminal/templates/terminal/database_command_list.html
0 → 100644
View file @
4efad4e5
apps/terminal/templates/terminal/database_session_detail.html
0 → 100644
View file @
4efad4e5
<!DOCTYPE html>
<html
lang=
"en"
>
<head>
<meta
charset=
"UTF-8"
>
<title>
Title
</title>
</head>
<body>
</body>
</html>
\ No newline at end of file
apps/terminal/templates/terminal/database_session_list.html
0 → 100644
View file @
4efad4e5
{% extends '_base_list.html' %}
{% load i18n %}
{% load static %}
{% load terminal_tags %}
{% load common_tags %}
{% block custom_head_css_js %}
<link
href=
"{% static 'css/plugins/datepicker/datepicker3.css' %}"
rel=
"stylesheet"
>
<link
href=
"{% static 'css/plugins/select2/select2.min.css' %}"
rel=
"stylesheet"
>
<script
src=
"{% static 'js/plugins/select2/select2.full.min.js' %}"
></script>
{% endblock %}
{% block content_left_head %}
{% endblock %}
{% block table_pagination %}
{% endblock %}
{% block table_search %}
{% endblock %}
{% block table_container %}
<table
class=
"table table-striped table-bordered table-hover"
id=
"session_table"
data-page=
"false"
>
<thead>
<tr>
<th
class=
"text-center"
></th>
<th
class=
"text-center"
>
{% trans 'ID' %}
</th>
<th
class=
"text-center"
>
{% trans 'User' %}
</th>
<th
class=
"text-center"
>
{% trans 'Database' %}
</th>
<th
class=
"text-center"
>
{% trans 'Database host' %}
</th>
<th
class=
"text-center"
>
{% trans 'Database user' %}
</th>
<th
class=
"text-center"
>
{% trans 'Database name' %}
</th>
<th
class=
"text-center"
>
{% trans 'Remote addr' %}
</th>
<th
class=
"text-center"
>
{% trans 'Login from' %}
</th>
<th
class=
"text-center"
>
{% trans 'Command' %}
</th>
<th
class=
"text-center"
>
{% trans 'Date start' %}
</th>
<th
class=
"text-center"
>
{% trans 'Duration' %}
</th>
<th
class=
"text-center"
>
{% trans 'Action' %}
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<div
class=
"hide"
id=
"daterange"
>
<div
class=
"form-group p-l-5"
id=
"date"
style=
"padding-left: 5px"
>
<div
class=
"input-daterange input-group p-l-5"
id=
"datepicker"
>
<span
class=
"input-group-addon"
><i
class=
"fa fa-calendar"
></i></span>
<input
type=
"text"
class=
"input-sm form-control"
style=
"width: 100px;"
id=
"date_from"
name=
"date_from"
value=
"{{ date_from|date:'Y-m-d' }}"
>
<span
class=
"input-group-addon"
>
to
</span>
<input
type=
"text"
class=
"input-sm form-control"
style=
"width: 100px;"
id=
"date_to"
name=
"date_to"
value=
"{{ date_to|date:'Y-m-d' }}"
>
</div>
</div>
</div>
<ul
class=
"dropdown-menu search-help"
>
<li><a
class=
"search-item"
data-value=
"user"
>
{% trans 'User' %}
</a></li>
<li><a
class=
"search-item"
data-value=
"database"
>
{% trans 'Database' %}
</a></li>
<li><a
class=
"search-item"
data-value=
"db_host"
>
{% trans 'Database host' %}
</a></li>
<li><a
class=
"search-item"
data-value=
"db_user"
>
{% trans 'Database user' %}
</a></li>
<li><a
class=
"search-item"
data-value=
"db_name"
>
{% trans 'Database name' %}
</a></li>
<li><a
class=
"search-item"
data-value=
"remote_addr"
>
{% trans 'Remote addr' %}
</a></li>
</ul>
{% endblock %}
{% block custom_foot_js %}
<script
src=
"{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"
></script>
<script
src=
"{% static 'js/plugins/datepicker/bootstrap-datepicker.zh-CN.min.js' %}"
></script>
<script>
function
terminateSession
(
data
)
{
function
success
()
{
window
.
setTimeout
(
function
()
{
window
.
location
.
reload
()
},
1000
)
}
var
success_message
=
'{% trans "Terminate task send, waiting ..." %}'
;
var
the_url
=
"{% url 'api-terminal:kill-session' %}"
;
requestApi
({
url
:
the_url
,
method
:
'POST'
,
body
:
JSON
.
stringify
(
data
),
success
:
success
,
success_message
:
success_message
});
}
var
sessionListUrl
=
"{% url 'api-terminal:database-session-list' %}?is_finished={% if type == "
online
" %}0{% else %}1{% endif %}"
;
var
dateFrom
=
"{{ date_from.timestamp }}"
;
var
dateTo
=
"{{ date_to.timestamp }}"
;
function
initTable
()
{
dateFrom
=
toSafeDateISOStr
(
dateFrom
*
1000
);
dateTo
=
toSafeDateISOStr
(
dateTo
*
1000
);
sessionListUrl
=
setUrlParam
(
sessionListUrl
,
"date_from"
,
dateFrom
);
sessionListUrl
=
setUrlParam
(
sessionListUrl
,
"date_to"
,
dateTo
);
var
options
=
{
ele
:
$
(
'#session_table'
),
ordering
:
false
,
columnDefs
:
[
{
targets
:
1
,
createdCell
:
function
(
td
,
cellData
,
rowData
,
i
)
{
var
index
=
i
+
1
;
var
data
=
'<a href="{% url '
terminal
:
database
-
session
-
detail
' pk=DEFAULT_PK %}">'
+
index
+
"</a>"
;
data
=
data
.
replace
(
"{{ DEFAULT_PK }}"
,
cellData
);
$
(
td
).
html
(
data
);
}},
{
targets
:
2
,
createdCell
:
function
(
td
,
cellData
)
{
var
data
=
htmlEscape
(
cellData
);
$
(
td
).
html
(
data
);
}},
{
targets
:
3
,
createdCell
:
function
(
td
,
cellData
)
{
var
data
=
htmlEscape
(
cellData
);
$
(
td
).
html
(
data
);
}},
{
targets
:
4
,
createdCell
:
function
(
td
,
cellData
)
{
var
data
=
htmlEscape
(
cellData
);
$
(
td
).
html
(
data
);
}},
{
targets
:
5
,
createdCell
:
function
(
td
,
cellData
)
{
var
data
=
htmlEscape
(
cellData
);
$
(
td
).
html
(
data
);
}},
{
targets
:
6
,
createdCell
:
function
(
td
,
cellData
)
{
var
data
=
htmlEscape
(
cellData
);
$
(
td
).
html
(
data
);
}},
{
targets
:
11
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
data
=
""
;
if
(
cellData
&&
rowData
.
date_start
)
{
data
=
timeOffset
(
rowData
.
date_start
,
cellData
)
}
$
(
td
).
html
(
data
);
}},
{
targets
:
12
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
btnGroup
=
""
;
var
replayBtn
=
'<a disabled data-session="sessionID" class="btn btn-xs btn-warning btn-replay" >{% trans "Replay" %}</a>'
;
replayBtn
=
replayBtn
.
replace
(
"sessionID"
,
rowData
.
id
);
if
(
rowData
.
can_replay
)
{
replayBtn
=
replayBtn
.
replace
(
"disabled"
,
""
)
}
var
termBtn
=
'<a class="btn btn-xs btn-danger btn-term" disabled value="sessionID" terminal="terminalID" >{% trans "Terminate" %}</a>'
;
if
(
"{{ request.user.is_org_admin }}"
===
"True"
)
{
termBtn
=
termBtn
.
replace
(
"disabled"
,
""
)
.
replace
(
"sessionID"
,
cellData
)
.
replace
(
"terminalID"
,
rowData
.
terminal
)
}
if
(
rowData
.
is_finished
)
{
btnGroup
+=
replayBtn
}
else
{
btnGroup
+=
termBtn
;
}
$
(
td
).
html
(
btnGroup
);
}}
],
ajax_url
:
sessionListUrl
,
columns
:
[
{
data
:
"id"
},
{
data
:
"id"
,
orderable
:
false
},
{
data
:
"user"
},
{
data
:
"database"
},
{
data
:
"db_host"
},
{
data
:
"db_user"
},
{
data
:
"db_name"
},
{
data
:
"remote_addr"
},
{
data
:
"login_from_display"
,
orderable
:
false
},
{
data
:
"command_amount"
,
orderable
:
false
},
{
data
:
"date_start"
},
{
data
:
"date_end"
,
orderable
:
false
},
{
data
:
"id"
,
orderable
:
false
}
],
op_html
:
$
(
'#actions'
).
html
(),
fb_html
:
$
(
"#daterange"
).
html
()
};
table
=
jumpserver
.
initServerSideDataTable
(
options
);
return
table
}
var
table
;
$
(
document
).
ready
(
function
()
{
table
=
initTable
(
"#session_table"
).
on
(
'init'
,
function
()
{
var
dateFromRef
=
$
(
"#date_from"
);
var
dateToRef
=
$
(
"#date_to"
);
var
options
=
{
format
:
"yyyy-mm-dd"
,
todayBtn
:
"linked"
,
keyboardNavigation
:
false
,
forceParse
:
false
,
calendarWeeks
:
true
,
autoclose
:
true
,
language
:
navigator
.
language
||
"en"
,
};
dateFromRef
.
datepicker
(
options
).
on
(
"changeDate"
,
function
()
{
if
(
!
$
(
this
).
val
())
{
return
}
var
value
=
$
(
this
).
val
()
+
' 0:0:0'
;
var
date
=
toSafeDateISOStr
(
value
);
var
url
=
table
.
ajax
.
url
();
url
=
setUrlParam
(
url
,
"date_from"
,
date
);
table
.
ajax
.
url
(
url
);
table
.
ajax
.
reload
();
});
dateToRef
.
datepicker
(
options
).
on
(
"changeDate"
,
function
()
{
if
(
!
$
(
this
).
val
())
{
return
}
var
value
=
$
(
this
).
val
()
+
' 23:59:59'
;
var
date
=
toSafeDateISOStr
(
value
);
var
url
=
table
.
ajax
.
url
();
url
=
setUrlParam
(
url
,
"date_to"
,
date
);
table
.
ajax
.
url
(
url
);
table
.
ajax
.
reload
();
});
});
}).
on
(
'click'
,
'.btn-term'
,
function
()
{
var
$this
=
$
(
this
);
var
session_id
=
$this
.
attr
(
'value'
);
var
data
=
[
session_id
];
terminateSession
(
data
)
}).
on
(
'click'
,
'.btn-replay'
,
function
()
{
var
sessionID
=
$
(
this
).
data
(
"session"
);
var
replayUrl
=
"/luna/replay/"
+
sessionID
;
window
.
open
(
replayUrl
,
"height=600, width=800, top=400, left=400, toolbar=no, menubar=no, scrollbars=no, location=no, status=no"
);
}).
on
(
"click"
,
'#session_table_filter input'
,
function
(
e
)
{
e
.
preventDefault
();
e
.
stopPropagation
();
var
offset1
=
$
(
'#session_table_filter input'
).
offset
();
var
x
=
offset1
.
left
;
var
y
=
offset1
.
top
;
var
offset
=
$
(
".search-help"
).
parent
().
offset
();
x
-=
offset
.
left
;
y
-=
offset
.
top
;
x
+=
18
;
y
+=
80
;
$
(
'.search-help'
).
css
({
"top"
:
y
+
"px"
,
"left"
:
x
+
"px"
,
"position"
:
"absolute"
});
$
(
'.dropdown-menu.search-help'
).
show
();
})
.
on
(
'click'
,
'.search-item'
,
function
(
e
)
{
e
.
preventDefault
();
e
.
stopPropagation
();
var
keyword
=
$
(
"#session_table_filter input"
);
var
value
=
$
(
this
).
data
(
'value'
);
var
old_value
=
keyword
.
val
();
var
new_value
=
old_value
+
' '
+
value
+
':'
;
keyword
.
val
(
new_value
.
trim
());
$
(
'.dropdown-menu.search-help'
).
hide
();
keyword
.
focus
()
})
.
on
(
'click'
,
'body'
,
function
(
e
)
{
$
(
'.dropdown-menu.search-help'
).
hide
()
})
</script>
{% endblock %}
apps/terminal/urls/views_urls.py
View file @
4efad4e5
...
...
@@ -18,12 +18,18 @@ urlpatterns = [
path
(
'web-terminal/'
,
views
.
WebTerminalView
.
as_view
(),
name
=
'web-terminal'
),
path
(
'web-sftp/'
,
views
.
WebSFTPView
.
as_view
(),
name
=
'web-sftp'
),
# Session view
path
(
'session-online/'
,
views
.
SessionOnlineListView
.
as_view
(),
name
=
'session-online-list'
),
path
(
'session-offline/'
,
views
.
SessionOfflineListView
.
as_view
(),
name
=
'session-offline-list'
),
path
(
'session/<uuid:pk>/'
,
views
.
SessionDetailView
.
as_view
(),
name
=
'session-detail'
),
# Asset session view
path
(
'asset/session-online/'
,
views
.
SessionOnlineListView
.
as_view
(),
name
=
'session-online-list'
),
path
(
'asset/session-offline/'
,
views
.
SessionOfflineListView
.
as_view
(),
name
=
'session-offline-list'
),
path
(
'asset/session/<uuid:pk>/'
,
views
.
SessionDetailView
.
as_view
(),
name
=
'session-detail'
),
# Databases session view
path
(
'database/session-online/'
,
views
.
DatabaseSessionOnlineListView
.
as_view
(),
name
=
'database-session-online-list'
),
path
(
'database/session-offline/'
,
views
.
DatabaseSessionOfflineListView
.
as_view
(),
name
=
'database-session-offline-list'
),
path
(
'database/session/<uuid:pk>/'
,
views
.
DatabaseSessionDetailView
.
as_view
(),
name
=
'database-session-detail'
),
# Command view
path
(
'command/'
,
views
.
CommandListView
.
as_view
(),
name
=
'command-list'
),
path
(
'asset/command/'
,
views
.
CommandListView
.
as_view
(),
name
=
'command-list'
),
# path('database/command/', views.DatabaseCommandListView.as_view(), name='database-command-list'),
]
apps/terminal/views/__init__.py
View file @
4efad4e5
# -*- coding: utf-8 -*-
#
from
.terminal
import
*
from
.session
import
*
from
.command
import
*
from
.asset_session
import
*
from
.asset_command
import
*
from
.database_session
import
*
apps/terminal/views/command.py
→
apps/terminal/views/
asset_
command.py
View file @
4efad4e5
...
...
@@ -11,7 +11,7 @@ __all__ = ['CommandListView']
class
CommandListView
(
PermissionsMixin
,
TemplateView
):
template_name
=
"terminal/command_list.html"
template_name
=
"terminal/
asset_
command_list.html"
permission_classes
=
[
IsOrgAdmin
|
IsAuditor
]
default_days_ago
=
5
...
...
apps/terminal/views/session.py
→
apps/terminal/views/
asset_
session.py
View file @
4efad4e5
...
...
@@ -4,14 +4,11 @@
from
django.views.generic
import
ListView
,
TemplateView
from
django.views.generic.edit
import
SingleObjectMixin
from
django.utils.translation
import
ugettext
as
_
from
django.utils
import
timezone
from
django.conf
import
settings
from
common.permissions
import
PermissionsMixin
,
IsOrgAdmin
,
IsAuditor
from
common.mixins
import
DatetimeSearchMixin
from
..models
import
Session
,
Command
,
Terminal
from
..models
import
Session
from
..backends
import
get_multi_command_storage
from
.
.
import
utils
from
.
base_session
import
BaseSessionListView
__all__
=
[
...
...
@@ -20,21 +17,9 @@ __all__ = [
]
class
SessionListView
(
PermissionsMixin
,
Template
View
):
class
SessionListView
(
BaseSessionList
View
):
model
=
Session
template_name
=
'terminal/session_list.html'
date_from
=
date_to
=
None
permission_classes
=
[
IsOrgAdmin
|
IsAuditor
]
default_days_ago
=
5
def
get_context_data
(
self
,
**
kwargs
):
now
=
timezone
.
now
()
context
=
{
'date_from'
:
now
-
timezone
.
timedelta
(
days
=
self
.
default_days_ago
),
'date_to'
:
now
,
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
template_name
=
'terminal/asset_session_list.html'
class
SessionOnlineListView
(
SessionListView
):
...
...
@@ -60,7 +45,7 @@ class SessionOfflineListView(SessionListView):
class
SessionDetailView
(
SingleObjectMixin
,
PermissionsMixin
,
ListView
):
template_name
=
'terminal/session_detail.html'
template_name
=
'terminal/
asset_
session_detail.html'
model
=
Session
object
=
None
permission_classes
=
[
IsOrgAdmin
|
IsAuditor
]
...
...
apps/terminal/views/base_session.py
0 → 100644
View file @
4efad4e5
# coding: utf-8
#
from
django.views.generic
import
TemplateView
from
django.utils
import
timezone
from
common.permissions
import
PermissionsMixin
,
IsOrgAdmin
,
IsAuditor
__all__
=
[
'BaseSessionListView'
]
class
BaseSessionListView
(
PermissionsMixin
,
TemplateView
):
model
=
None
template_name
=
None
date_from
=
date_to
=
None
permission_classes
=
[
IsOrgAdmin
|
IsAuditor
]
default_days_ago
=
5
def
get_context_data
(
self
,
**
kwargs
):
now
=
timezone
.
now
()
context
=
{
'date_from'
:
now
-
timezone
.
timedelta
(
days
=
self
.
default_days_ago
),
'date_to'
:
now
,
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
apps/terminal/views/database_session.py
0 → 100644
View file @
4efad4e5
# -*- coding: utf-8 -*-
#
from
django.views.generic
import
ListView
from
django.views.generic.edit
import
SingleObjectMixin
from
common.permissions
import
PermissionsMixin
,
IsOrgAdmin
,
IsAuditor
from
..backends
import
get_multi_command_storage
from
django.utils.translation
import
ugettext
as
_
from
..models
import
DatabaseSession
from
.base_session
import
BaseSessionListView
__all__
=
[
'DatabaseSessionOnlineListView'
,
'DatabaseSessionOfflineListView'
,
'DatabaseSessionDetailView'
]
class
DatabaseSessionListView
(
BaseSessionListView
):
model
=
DatabaseSession
template_name
=
'terminal/database_session_list.html'
class
DatabaseSessionOnlineListView
(
DatabaseSessionListView
):
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
_
(
'Sessions'
),
'action'
:
_
(
'Session online list'
),
'type'
:
'online'
,
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
class
DatabaseSessionOfflineListView
(
DatabaseSessionListView
):
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
_
(
'Sessions'
),
'action'
:
_
(
'Session offline'
),
'type'
:
'offline'
,
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
class
DatabaseSessionDetailView
(
SingleObjectMixin
,
PermissionsMixin
,
ListView
):
template_name
=
'terminal/database_session_detail.html'
model
=
DatabaseSession
object
=
None
permission_classes
=
[
IsOrgAdmin
|
IsAuditor
]
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
self
.
object
=
self
.
get_object
(
queryset
=
self
.
model
.
objects
.
all
())
return
super
()
.
get
(
request
,
*
args
,
**
kwargs
)
def
get_queryset
(
self
):
command_store
=
get_multi_command_storage
()
return
command_store
.
filter
(
session
=
self
.
object
.
id
)
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
_
(
'Sessions'
),
'action'
:
_
(
'Session detail'
),
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
\ No newline at end of file
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