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
5f6af8c0
Commit
5f6af8c0
authored
Jul 03, 2019
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Update] 修改command列表
parent
e7d600ee
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
118 additions
and
60 deletions
+118
-60
system_user_list.html
apps/assets/templates/assets/system_user_list.html
+1
-1
permissions.py
apps/common/permissions.py
+2
-0
jumpserver.css
apps/static/css/jumpserver.css
+10
-1
jumpserver.js
apps/static/js/jumpserver.js
+7
-3
bootstrap-datepicker.zh-CN.min.js
...c/js/plugins/datepicker/bootstrap-datepicker.zh-CN.min.js
+2
-0
session.py
apps/terminal/api/session.py
+29
-5
db.py
apps/terminal/backends/command/db.py
+6
-3
command_list.html
apps/terminal/templates/terminal/command_list.html
+42
-18
command.py
apps/terminal/views/command.py
+7
-17
user_list.html
apps/users/templates/users/user_list.html
+12
-12
No files found.
apps/assets/templates/assets/system_user_list.html
View file @
5f6af8c0
...
...
@@ -46,7 +46,7 @@
<thead>
<tr>
<th
class=
"text-center"
>
<input
type=
"checkbox"
id=
"check_all"
class=
"ipt_check_all"
>
<input
type=
"checkbox"
id=
"check_all"
class=
"ipt_check_all"
>
</th>
<th
class=
"text-center"
>
{% trans 'Name' %}
</th>
<th
class=
"text-center"
>
{% trans 'Username' %}
</th>
...
...
apps/common/permissions.py
View file @
5f6af8c0
...
...
@@ -146,6 +146,8 @@ class CanUpdateSuperUser(permissions.BasePermission):
def
has_object_permission
(
self
,
request
,
view
,
obj
):
if
request
.
method
in
[
'GET'
,
'OPTIONS'
]:
return
True
if
str
(
request
.
user
.
id
)
==
str
(
obj
.
id
):
return
False
if
request
.
user
.
is_superuser
:
return
True
if
hasattr
(
obj
,
'is_superuser'
)
and
obj
.
is_superuser
:
...
...
apps/static/css/jumpserver.css
View file @
5f6af8c0
...
...
@@ -304,7 +304,7 @@ table.dataTable tbody td.selected td i.text-navy {
div
.dataTables_wrapper
div
.dataTables_filter
,
.dataTables_length
{
float
:
right
!important
;
//
float
:
right
!important
;
}
div
.dataTables_wrapper
div
.dataTables_filter
{
...
...
@@ -466,3 +466,11 @@ div.dataTables_wrapper div.dataTables_filter {
span
.select2-selection__placeholder
{
line-height
:
34px
!important
;
}
.p-l-5
{
padding-left
:
5px
;
}
.p-r-5
{
padding-right
:
5px
;
}
\ No newline at end of file
apps/static/js/jumpserver.js
View file @
5f6af8c0
...
...
@@ -567,7 +567,8 @@ jumpserver.initServerSideDataTable = function (options) {
};
var
table
=
ele
.
DataTable
({
pageLength
:
options
.
pageLength
||
15
,
dom
:
options
.
dom
||
'<"#uc.pull-left">fltr<"row m-t"<"col-md-8"<"#op.col-md-6"><"col-md-6 text-center"i>><"col-md-4"p>>'
,
// dom: options.dom || '<"#uc.pull-left">fltr<"row m-t"<"col-md-8"<"#op.col-md-6"><"col-md-6 text-center"i>><"col-md-4"p>>',
dom
:
options
.
dom
||
'<"#uc.pull-left"><"pull-right"<"inline"l><"#fb.inline"><"inline"f><"#fa.inline">>tr<"row m-t"<"col-md-8"<"#op.col-md-6"><"col-md-6 text-center"i>><"col-md-4"p>>'
,
order
:
options
.
order
||
[],
buttons
:
[],
columnDefs
:
columnDefs
,
...
...
@@ -668,8 +669,6 @@ jumpserver.initServerSideDataTable = function (options) {
})
}
}).
on
(
'draw'
,
function
(){
$
(
'#op'
).
html
(
options
.
op_html
||
''
);
$
(
'#uc'
).
html
(
options
.
uc_html
||
''
);
$
(
'[data-toggle="popover"]'
).
popover
({
html
:
true
,
placement
:
'bottom'
,
...
...
@@ -691,6 +690,11 @@ jumpserver.initServerSideDataTable = function (options) {
table
.
rows
(
index
).
select
()
}
});
}).
on
(
"init"
,
function
()
{
$
(
'#op'
).
html
(
options
.
op_html
||
''
);
$
(
'#uc'
).
html
(
options
.
uc_html
||
''
);
$
(
'#fb'
).
html
(
options
.
fb_html
||
''
);
$
(
'#fa'
).
html
(
options
.
fa_html
||
''
);
});
var
table_id
=
table
.
settings
()[
0
].
sTableId
;
$
(
'#'
+
table_id
+
' .ipt_check_all'
).
on
(
'click'
,
function
()
{
...
...
apps/static/js/plugins/datepicker/bootstrap-datepicker.zh-CN.min.js
0 → 100644
View file @
5f6af8c0
!
function
(
a
){
a
.
fn
.
datepicker
.
dates
[
"zh-CN"
]
=
{
days
:[
"星期日"
,
"星期一"
,
"星期二"
,
"星期三"
,
"星期四"
,
"星期五"
,
"星期六"
],
daysShort
:[
"周日"
,
"周一"
,
"周二"
,
"周三"
,
"周四"
,
"周五"
,
"周六"
],
daysMin
:[
"日"
,
"一"
,
"二"
,
"三"
,
"四"
,
"五"
,
"六"
],
months
:[
"一月"
,
"二月"
,
"三月"
,
"四月"
,
"五月"
,
"六月"
,
"七月"
,
"八月"
,
"九月"
,
"十月"
,
"十一月"
,
"十二月"
],
monthsShort
:[
"1月"
,
"2月"
,
"3月"
,
"4月"
,
"5月"
,
"6月"
,
"7月"
,
"8月"
,
"9月"
,
"10月"
,
"11月"
,
"12月"
],
today
:
"今天"
,
monthsTitle
:
"选择月份"
,
clear
:
"清除"
,
format
:
"yyyy-mm-dd"
,
titleFormat
:
"yyyy年mm月"
,
weekStart
:
1
}}(
jQuery
);
\ No newline at end of file
apps/terminal/api/session.py
View file @
5f6af8c0
...
...
@@ -7,6 +7,7 @@ from django.shortcuts import get_object_or_404
from
django.core.files.storage
import
default_storage
from
django.http
import
HttpResponseNotFound
from
django.conf
import
settings
from
django.utils
import
timezone
from
rest_framework.pagination
import
LimitOffsetPagination
from
rest_framework
import
viewsets
from
rest_framework.response
import
Response
...
...
@@ -39,10 +40,14 @@ class SessionViewSet(BulkModelViewSet):
terminal
=
get_object_or_404
(
Terminal
,
id
=
terminal_id
)
queryset
=
queryset
.
filter
(
terminal
=
terminal
)
return
queryset
return
queryset
def
get_object
(
self
):
# 解决guacamole更新session时并发导致幽灵会话的问题
obj
=
super
()
.
get_object
()
if
self
.
request
.
method
in
(
'PATCH'
,
):
queryset
=
queryset
.
select_for_update
()
return
queryset
obj
=
obj
.
select_for_update
()
return
obj
def
perform_create
(
self
,
serializer
):
if
hasattr
(
self
.
request
.
user
,
'terminal'
):
...
...
@@ -71,14 +76,33 @@ class CommandViewSet(viewsets.ModelViewSet):
command_store
=
get_command_storage
()
serializer_class
=
SessionCommandSerializer
pagination_class
=
LimitOffsetPagination
permission_classes
=
(
IsOrgAdminOrAppUser
|
IsAuditor
,)
filter_fields
=
(
"asset"
,
"system_user"
,
"user"
,
"input"
)
permission_classes
=
[
IsOrgAdminOrAppUser
|
IsAuditor
]
filter_fields
=
[
"asset"
,
"system_user"
,
"user"
,
"input"
,
"session"
,
]
default_days_ago
=
5
def
get_queryset
(
self
):
date_from
,
date_to
=
self
.
get_date_range
()
multi_command_storage
=
get_multi_command_storage
()
queryset
=
multi_command_storage
.
filter
()
queryset
=
multi_command_storage
.
filter
(
date_from
=
date_from
,
date_to
=
date_to
)
return
queryset
def
get_filter_fields
(
self
):
fields
=
self
.
filter_fields
fields
.
extend
([
"date_from"
,
"date_to"
])
return
fields
def
get_date_range
(
self
):
now
=
timezone
.
now
()
days_ago
=
now
-
timezone
.
timedelta
(
days
=
self
.
default_days_ago
)
default_start_st
=
days_ago
.
timestamp
()
default_end_st
=
now
.
timestamp
()
query_params
=
self
.
request
.
query_params
date_from_st
=
query_params
.
get
(
"date_from"
)
or
default_start_st
date_to_st
=
query_params
.
get
(
"date_to"
)
or
default_end_st
return
int
(
date_from_st
),
int
(
date_to_st
)
def
create
(
self
,
request
,
*
args
,
**
kwargs
):
serializer
=
self
.
serializer_class
(
data
=
request
.
data
,
many
=
True
)
if
serializer
.
is_valid
():
...
...
apps/terminal/backends/command/db.py
View file @
5f6af8c0
...
...
@@ -71,9 +71,13 @@ class CommandStore(CommandBase):
if
not
date_to
and
not
session
:
date_to
=
date_to_default
if
date_from
is
not
None
:
filter_kwargs
[
'timestamp__gte'
]
=
int
(
date_from
.
timestamp
())
if
isinstance
(
date_from
,
datetime
.
datetime
):
date_from
=
date_from
.
timestamp
()
filter_kwargs
[
'timestamp__gte'
]
=
int
(
date_from
)
if
date_to
is
not
None
:
filter_kwargs
[
'timestamp__lte'
]
=
int
(
date_to
.
timestamp
())
if
isinstance
(
date_to
,
datetime
.
datetime
):
date_to
=
date_to
.
timestamp
()
filter_kwargs
[
'timestamp__lte'
]
=
int
(
date_to
)
if
user
:
filter_kwargs
[
"user"
]
=
user
...
...
@@ -85,7 +89,6 @@ class CommandStore(CommandBase):
filter_kwargs
[
'input__icontains'
]
=
input
if
session
:
filter_kwargs
[
'session'
]
=
session
return
filter_kwargs
def
filter
(
self
,
date_from
=
None
,
date_to
=
None
,
...
...
apps/terminal/templates/terminal/command_list.html
View file @
5f6af8c0
...
...
@@ -3,10 +3,7 @@
{% load static %}
{% load common_tags %}
{% block custom_head_css_js %}
<link
href=
"{% static "
css
/
plugins
/
footable
/
footable
.
core
.
css
"
%}"
rel=
"stylesheet"
>
<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>
<style>
.toggle
{
cursor
:
pointer
;
...
...
@@ -23,6 +20,7 @@
{% block table_search %}
{% endblock %}
{% block table_container %}
<table
class=
"table table-striped table-bordered table-hover"
id=
"command_table"
data-page=
"false"
>
<thead>
...
...
@@ -53,35 +51,60 @@
</div>
</div>
<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=
"asset"
>
{% trans 'Asset' %}
</a></li>
<li><a
class=
"search-item"
data-value=
"system_user"
>
{% trans 'System user' %}
</a></li>
<li><a
class=
"search-item"
data-value=
"
command
"
>
{% trans 'Command' %}
</a></li>
<li><a
class=
"search-item"
data-value=
"
input
"
>
{% trans 'Command' %}
</a></li>
</ul>
{% endblock %}
{% block content_bottom_left %}{% endblock %}
{% block custom_foot_js %}
<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' %}"
charset=
"UTF-8
"
></script>
<script
src=
"{% static 'js/plugins/datepicker/bootstrap-datepicker.
zh-CN.min.js' %}"
charset=
"UTF-8
"
></script>
<script>
var
table
;
$
(
document
).
ready
(
function
()
{
$
(
'.footable'
).
footable
();
$
(
'.select2'
).
select2
({
dropdownAutoWidth
:
true
,
width
:
'auto'
});
$
(
'#date .input-daterange'
).
datepicker
({
table
=
initTable
().
on
(
"init"
,
function
()
{
var
dateFromRef
=
$
(
"#date_from"
);
var
dateToRef
=
$
(
"#date_to"
);
let
options
=
{
format
:
"yyyy-mm-dd"
,
todayBtn
:
"linked"
,
keyboardNavigation
:
false
,
forceParse
:
false
,
calendarWeeks
:
true
,
autoclose
:
true
autoclose
:
true
,
language
:
navigator
.
language
||
"en"
,
};
dateFromRef
.
datepicker
(
options
).
on
(
"changeDate"
,
function
()
{
let
date
=
new
Date
(
$
(
this
).
val
()
+
' 0:0:0'
);
let
url
=
table
.
ajax
.
url
();
url
=
setUrlParam
(
url
,
"date_from"
,
date
.
getTime
()
/
1000
);
table
.
ajax
.
url
(
url
);
table
.
ajax
.
reload
();
console
.
log
(
"On change"
)
});
dateToRef
.
datepicker
(
options
).
on
(
"changeDate"
,
function
()
{
let
date
=
new
Date
(
$
(
this
).
val
()
+
' 23:59:59'
);
let
url
=
table
.
ajax
.
url
();
url
=
setUrlParam
(
url
,
"date_to"
,
date
.
getTime
()
/
1000
);
table
.
ajax
.
url
(
url
);
table
.
ajax
.
reload
();
});
});
initTable
();
})
.
on
(
'click'
,
'#btn_bulk_update'
,
function
(){
var
action
=
$
(
'#slct_bulk_update'
).
val
();
...
...
@@ -100,13 +123,11 @@ $(document).ready(function () {
var
offset1
=
$
(
'#command_table_filter input'
).
offset
();
var
x
=
offset1
.
left
;
var
y
=
offset1
.
top
;
console
.
log
(
x
,
y
)
var
offset
=
$
(
".search-help"
).
parent
().
offset
();
x
-=
offset
.
left
;
y
-=
offset
.
top
;
x
+=
18
;
y
+=
80
;
console
.
log
(
x
,
y
)
$
(
'.search-help'
).
css
({
"top"
:
y
+
"px"
,
"left"
:
x
+
"px"
,
"position"
:
"absolute"
});
$
(
'.dropdown-menu.search-help'
).
show
();
})
...
...
@@ -149,7 +170,9 @@ $(document).ready(function () {
}
}).
on
(
'click'
,
'body'
,
function
(
e
)
{
$
(
'.dropdown-menu.search-help'
).
hide
()
})
}).
on
(
'change'
,
'#date_start'
,
function
()
{
console
.
log
(
"date change"
)
});
...
...
@@ -186,7 +209,8 @@ function initTable() {
{
data
:
"session"
},
{
data
:
"timestamp"
,
width
:
"160px"
},
],
select
:
{},
op_html
:
$
(
'#actions'
).
html
()
op_html
:
$
(
'#actions'
).
html
(),
fb_html
:
$
(
"#daterange"
).
html
(),
};
table
=
jumpserver
.
initServerSideDataTable
(
options
);
return
table
...
...
apps/terminal/views/command.py
View file @
5f6af8c0
# -*- coding: utf-8 -*-
#
from
django.views.generic
import
ListView
,
View
from
django.conf
import
settings
from
django.views.generic
import
View
,
TemplateView
from
django.utils.translation
import
ugettext
as
_
from
django.http
import
HttpResponse
from
django.template
import
loader
from
django.utils
import
timezone
import
time
from
common.mixins
import
DatetimeSearchMixin
from
common.permissions
import
PermissionsMixin
,
IsOrgAdmin
,
IsAuditor
from
..models
import
Command
from
..
import
utils
from
..backends
import
get_multi_command_storage
__all__
=
[
'CommandListView'
,
'CommandExportView'
]
common_storage
=
get_multi_command_storage
()
class
CommandListView
(
DatetimeSearchMixin
,
PermissionsMixin
,
ListView
):
model
=
Command
class
CommandListView
(
DatetimeSearchMixin
,
PermissionsMixin
,
TemplateView
):
template_name
=
"terminal/command_list.html"
context_object_name
=
'command_list'
paginate_by
=
settings
.
DISPLAY_PER_PAGE
date_from
=
date_to
=
None
permission_classes
=
[
IsOrgAdmin
|
IsAuditor
]
def
get_queryset
(
self
):
filter_kwargs
=
dict
()
filter_kwargs
[
'date_from'
]
=
self
.
date_from
filter_kwargs
[
'date_to'
]
=
self
.
date_to
queryset
=
common_storage
.
filter
(
**
filter_kwargs
)
return
queryset
default_days_ago
=
5
def
get_context_data
(
self
,
**
kwargs
):
now
=
timezone
.
now
()
context
=
{
'app'
:
_
(
'Sessions'
),
'action'
:
_
(
'Command list'
),
'date_from'
:
self
.
date_from
,
'date_to'
:
self
.
date_to
,
'date_from'
:
now
-
timezone
.
timedelta
(
days
=
self
.
default_days_ago
)
,
'date_to'
:
now
,
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
...
...
apps/users/templates/users/user_list.html
View file @
5f6af8c0
{% extends '_base_list.html' %}
{% load i18n static %}
{% block table_search %}
<div
class=
"
"
style=
"float: right"
>
<div
class=
"
pull-right"
>
<div
class=
" btn-group"
>
<button
data-toggle=
"dropdown"
class=
"btn btn-default btn-sm dropdown-toggle"
>
CSV
<span
class=
"caret"
></span></button>
<ul
class=
"dropdown-menu"
>
...
...
@@ -92,23 +92,23 @@ function initTable() {
}},
{
targets
:
7
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
update_btn
=
""
;
{
#
if
(
rowData
.
role
===
'Admin'
&&
(
'{{ request.user.role }}'
!==
'Admin'
))
{
#
}
{
#
update_btn
=
'<a class="btn btn-xs disabled btn-info">{% trans "Update" %}</a>'
;
#
}
{
#
}
#
}
{
#
else
{
#
}
if
(
rowData
.
role
===
'Admin'
&&
(
'{{ request.user.role }}'
!==
'Admin'
))
{
update_btn
=
'<a class="btn btn-xs disabled btn-info">{% trans "Update" %}</a>'
;
}
else
{
update_btn
=
'<a href="{% url "users:user-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'
.
replace
(
'00000000-0000-0000-0000-000000000000'
,
cellData
);
{
#
}
#
}
}
var
del_btn
=
""
;
{
#
if
(
rowData
.
id
===
1
||
rowData
.
username
===
"admin"
||
rowData
.
username
===
"{{ request.user.username }}"
||
(
rowData
.
role
===
'Admin'
&&
(
'{{ request.user.role }}'
!==
'Admin'
)))
{
#
}
{
#
del_btn
=
'<a class="btn btn-xs btn-danger m-l-xs" disabled>{% trans "Delete" %}</a>'
#
}
{
#
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
)
#
}
{
#
.
replace
(
'99991938'
,
rowData
.
name
);
#
}
{
#
}
else
{
#
}
if
(
rowData
.
id
===
1
||
rowData
.
username
===
"admin"
||
rowData
.
username
===
"{{ request.user.username }}"
||
(
rowData
.
role
===
'Admin'
&&
(
'{{ request.user.role }}'
!==
'Admin'
)))
{
del_btn
=
'<a class="btn btn-xs btn-danger m-l-xs" disabled>{% trans "Delete" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
)
.
replace
(
'99991938'
,
rowData
.
name
);
}
else
{
del_btn
=
'<a class="btn btn-xs btn-danger m-l-xs btn_user_delete" data-uid="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Delete" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
)
.
replace
(
'99991938'
,
rowData
.
name
);
{
#
}
#
}
}
$
(
td
).
html
(
update_btn
+
del_btn
)
}}],
ajax_url
:
'{% url "api-users:user-list" %}'
,
...
...
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