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
53c532a6
Unverified
Commit
53c532a6
authored
Apr 19, 2018
by
老广
Committed by
GitHub
Apr 19, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1213 from jumpserver/dev
更新资产选择
parents
45b13abe
035dd16b
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
337 additions
and
218 deletions
+337
-218
node.py
apps/assets/api/node.py
+14
-0
asset.py
apps/assets/models/asset.py
+1
-1
node.py
apps/assets/models/node.py
+2
-2
tasks.py
apps/assets/tasks.py
+3
-0
_asset_list_modal.html
apps/assets/templates/assets/_asset_list_modal.html
+98
-105
asset_detail.html
apps/assets/templates/assets/asset_detail.html
+2
-2
asset_list.html
apps/assets/templates/assets/asset_list.html
+0
-0
domain_create_update.html
apps/assets/templates/assets/domain_create_update.html
+16
-4
domain_gateway_list.html
apps/assets/templates/assets/domain_gateway_list.html
+0
-5
label_create_update.html
apps/assets/templates/assets/label_create_update.html
+21
-4
system_user_detail.html
apps/assets/templates/assets/system_user_detail.html
+2
-2
api_urls.py
apps/assets/urls/api_urls.py
+1
-0
asset.py
apps/assets/views/asset.py
+11
-8
fields.py
apps/common/fields.py
+28
-2
django.mo
apps/i18n/zh/LC_MESSAGES/django.mo
+0
-0
django.po
apps/i18n/zh/LC_MESSAGES/django.po
+0
-0
urls.py
apps/jumpserver/urls.py
+4
-3
asset_permission_asset.html
apps/perms/templates/perms/asset_permission_asset.html
+38
-51
asset_permission_create_update.html
...perms/templates/perms/asset_permission_create_update.html
+32
-14
asset_permission_detail.html
apps/perms/templates/perms/asset_permission_detail.html
+2
-2
asset_permission_user.html
apps/perms/templates/perms/asset_permission_user.html
+3
-3
views.py
apps/perms/views.py
+2
-2
jumpserver.js
apps/static/js/jumpserver.js
+39
-5
_modal.html
apps/templates/_modal.html
+7
-0
_nav.html
apps/templates/_nav.html
+1
-1
api.py
apps/terminal/api.py
+1
-1
user.py
apps/users/models/user.py
+9
-1
No files found.
apps/assets/api/node.py
View file @
53c532a6
...
@@ -32,6 +32,7 @@ __all__ = [
...
@@ -32,6 +32,7 @@ __all__ = [
'NodeViewSet'
,
'NodeChildrenApi'
,
'NodeViewSet'
,
'NodeChildrenApi'
,
'NodeAssetsApi'
,
'NodeWithAssetsApi'
,
'NodeAssetsApi'
,
'NodeWithAssetsApi'
,
'NodeAddAssetsApi'
,
'NodeRemoveAssetsApi'
,
'NodeAddAssetsApi'
,
'NodeRemoveAssetsApi'
,
'NodeReplaceAssetsApi'
,
'NodeAddChildrenApi'
,
'RefreshNodeHardwareInfoApi'
,
'NodeAddChildrenApi'
,
'RefreshNodeHardwareInfoApi'
,
'TestNodeConnectiveApi'
'TestNodeConnectiveApi'
]
]
...
@@ -191,6 +192,19 @@ class NodeRemoveAssetsApi(generics.UpdateAPIView):
...
@@ -191,6 +192,19 @@ class NodeRemoveAssetsApi(generics.UpdateAPIView):
instance
.
assets
.
remove
(
*
tuple
(
assets
))
instance
.
assets
.
remove
(
*
tuple
(
assets
))
class
NodeReplaceAssetsApi
(
generics
.
UpdateAPIView
):
serializer_class
=
serializers
.
NodeAssetsSerializer
queryset
=
Node
.
objects
.
all
()
permission_classes
=
(
IsSuperUser
,)
instance
=
None
def
perform_update
(
self
,
serializer
):
assets
=
serializer
.
validated_data
.
get
(
'assets'
)
instance
=
self
.
get_object
()
for
asset
in
assets
:
asset
.
nodes
.
set
([
instance
])
class
RefreshNodeHardwareInfoApi
(
APIView
):
class
RefreshNodeHardwareInfoApi
(
APIView
):
permission_classes
=
(
IsSuperUser
,)
permission_classes
=
(
IsSuperUser
,)
model
=
Node
model
=
Node
...
...
apps/assets/models/asset.py
View file @
53c532a6
...
@@ -49,6 +49,7 @@ class Asset(models.Model):
...
@@ -49,6 +49,7 @@ class Asset(models.Model):
ip
=
models
.
GenericIPAddressField
(
max_length
=
32
,
verbose_name
=
_
(
'IP'
),
db_index
=
True
)
ip
=
models
.
GenericIPAddressField
(
max_length
=
32
,
verbose_name
=
_
(
'IP'
),
db_index
=
True
)
hostname
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
'Hostname'
))
hostname
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
'Hostname'
))
port
=
models
.
IntegerField
(
default
=
22
,
verbose_name
=
_
(
'Port'
))
port
=
models
.
IntegerField
(
default
=
22
,
verbose_name
=
_
(
'Port'
))
platform
=
models
.
CharField
(
max_length
=
128
,
choices
=
PLATFORM_CHOICES
,
default
=
'Linux'
,
verbose_name
=
_
(
'Platform'
))
domain
=
models
.
ForeignKey
(
"assets.Domain"
,
null
=
True
,
blank
=
True
,
related_name
=
'assets'
,
verbose_name
=
_
(
"Domain"
),
on_delete
=
models
.
SET_NULL
)
domain
=
models
.
ForeignKey
(
"assets.Domain"
,
null
=
True
,
blank
=
True
,
related_name
=
'assets'
,
verbose_name
=
_
(
"Domain"
),
on_delete
=
models
.
SET_NULL
)
nodes
=
models
.
ManyToManyField
(
'assets.Node'
,
default
=
default_node
,
related_name
=
'assets'
,
verbose_name
=
_
(
"Nodes"
))
nodes
=
models
.
ManyToManyField
(
'assets.Node'
,
default
=
default_node
,
related_name
=
'assets'
,
verbose_name
=
_
(
"Nodes"
))
is_active
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
'Is active'
))
is_active
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
'Is active'
))
...
@@ -72,7 +73,6 @@ class Asset(models.Model):
...
@@ -72,7 +73,6 @@ class Asset(models.Model):
disk_total
=
models
.
CharField
(
max_length
=
1024
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Disk total'
))
disk_total
=
models
.
CharField
(
max_length
=
1024
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Disk total'
))
disk_info
=
models
.
CharField
(
max_length
=
1024
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Disk info'
))
disk_info
=
models
.
CharField
(
max_length
=
1024
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Disk info'
))
platform
=
models
.
CharField
(
max_length
=
128
,
choices
=
PLATFORM_CHOICES
,
default
=
'Linux'
,
verbose_name
=
_
(
'Platform'
))
os
=
models
.
CharField
(
max_length
=
128
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'OS'
))
os
=
models
.
CharField
(
max_length
=
128
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'OS'
))
os_version
=
models
.
CharField
(
max_length
=
16
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'OS version'
))
os_version
=
models
.
CharField
(
max_length
=
16
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'OS version'
))
os_arch
=
models
.
CharField
(
max_length
=
16
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'OS arch'
))
os_arch
=
models
.
CharField
(
max_length
=
16
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'OS arch'
))
...
...
apps/assets/models/node.py
View file @
53c532a6
...
@@ -19,7 +19,7 @@ class Node(models.Model):
...
@@ -19,7 +19,7 @@ class Node(models.Model):
is_asset
=
False
is_asset
=
False
def
__str__
(
self
):
def
__str__
(
self
):
return
self
.
value
return
self
.
full_
value
@property
@property
def
name
(
self
):
def
name
(
self
):
...
@@ -30,7 +30,7 @@ class Node(models.Model):
...
@@ -30,7 +30,7 @@ class Node(models.Model):
if
self
==
self
.
__class__
.
root
():
if
self
==
self
.
__class__
.
root
():
return
self
.
value
return
self
.
value
else
:
else
:
return
'{}
/{}'
.
format
(
self
.
value
,
self
.
parent
.
full_
value
)
return
'{}
/ {}'
.
format
(
self
.
parent
.
full_value
,
self
.
value
)
@property
@property
def
level
(
self
):
def
level
(
self
):
...
...
apps/assets/tasks.py
View file @
53c532a6
...
@@ -96,6 +96,9 @@ def update_assets_hardware_info_util(assets, task_name=None):
...
@@ -96,6 +96,9 @@ def update_assets_hardware_info_util(assets, task_name=None):
task_name
=
_
(
"更新资产硬件信息"
)
task_name
=
_
(
"更新资产硬件信息"
)
tasks
=
const
.
UPDATE_ASSETS_HARDWARE_TASKS
tasks
=
const
.
UPDATE_ASSETS_HARDWARE_TASKS
hostname_list
=
[
asset
.
hostname
for
asset
in
assets
if
asset
.
is_active
and
asset
.
is_unixlike
()]
hostname_list
=
[
asset
.
hostname
for
asset
in
assets
if
asset
.
is_active
and
asset
.
is_unixlike
()]
if
not
hostname_list
:
logger
.
info
(
"Not hosts get, may be asset is not active or not unixlike platform"
)
return
{}
task
,
created
=
update_or_create_ansible_task
(
task
,
created
=
update_or_create_ansible_task
(
task_name
,
hosts
=
hostname_list
,
tasks
=
tasks
,
pattern
=
'all'
,
task_name
,
hosts
=
hostname_list
,
tasks
=
tasks
,
pattern
=
'all'
,
options
=
const
.
TASK_OPTIONS
,
run_as_admin
=
True
,
created_by
=
'System'
,
options
=
const
.
TASK_OPTIONS
,
run_as_admin
=
True
,
created_by
=
'System'
,
...
...
apps/assets/templates/assets/_asset_list_modal.html
View file @
53c532a6
{% extends '_modal.html' %}
{% extends '_modal.html' %}
{% load i18n %}
{% load i18n %}
{% load static %}
{% block modal_class %}modal-lg{% endblock %}
{% block modal_class %}modal-lg{% endblock %}
{% block modal_id %}asset_list_modal{% endblock %}
{% block modal_id %}asset_list_modal{% endblock %}
{
#{% block modal_title%}{% trans "Please select assets" %}{% endblock %}#
}
{
% block modal_title%}{% trans "Asset list" %}{% endblock %
}
{% block modal_body %}
{% block modal_body %}
{#
<div
class=
"btn-group"
style=
"float: right"
>
#}
<link
href=
"{% static 'css/plugins/ztree/awesomeStyle/awesome.css' %}"
rel=
"stylesheet"
>
{#
<button
data-toggle=
"dropdown"
class=
"btn btn-default btn-sm dropdown-toggle"
>
{% trans 'Label' %}
<span
class=
"caret"
></span></button>
#}
<script
type=
"text/javascript"
src=
"{% static 'js/plugins/ztree/jquery.ztree.all.min.js' %}"
></script>
{#
<ul
class=
"dropdown-menu labels"
>
#}
<script
src=
"{% static 'js/jquery.form.min.js' %}"
></script>
{# {% for label in labels %}#}
<style>
{#
<li><a
style=
"font-weight: bolder"
>
{{ label.name }}:{{ label.value }}
</a></li>
#}
.inmodal
.modal-header
{
{# {% endfor %}#}
padding
:
10px
10px
;
{#
</ul>
#}
text-align
:
center
;
{#
</div>
#}
}
<table
class=
"table table-striped table-bordered table-hover "
id=
"asset_modal_table"
width=
"100%"
>
<thead>
#assetTree2
.ztree
*
{
<tr>
background-color
:
#f8fafb
;
<th
class=
"text-center"
><input
type=
"checkbox"
class=
"ipt_check_all"
></th>
}
<th
class=
"text-center"
>
{% trans 'Hostname' %}
</th>
#assetTree2
.ztree
{
<th
class=
"text-center"
>
{% trans 'IP' %}
</th>
background-color
:
#f8fafb
;
<th
class=
"text-center"
>
{% trans 'Hardware' %}
</th>
}
<th
class=
"text-center"
>
{% trans 'Active' %}
</th>
</style>
<th
class=
"text-center"
>
{% trans 'Reachable' %}
</th>
<th
class=
"text-center"
>
{% trans 'Action' %}
</th>
<div
class=
"wrapper wrapper-content"
>
</tr>
<div
class=
"row"
>
</thead>
<div
class=
"col-lg-3"
id=
"split-left"
style=
"padding-left: 3px"
>
<tbody>
<div
class=
"ibox float-e-margins"
>
</tbody>
<div
class=
"ibox-content mailbox-content"
style=
"padding-top: 0;padding-left: 1px"
>
</table>
<div
class=
"file-manager "
>
<div
id=
"actions"
class=
"hide"
>
<div
id=
"assetTree2"
class=
"ztree"
>
<div
class=
"input-group"
>
</div>
<select
class=
"form-control m-b"
style=
"width: auto"
id=
"slct_bulk_update"
>
<div
class=
"clearfix"
></div>
<option
value=
"delete"
>
{% trans 'Delete selected' %}
</option>
</div>
<option
value=
"update"
>
{% trans 'Update selected' %}
</option>
</div>
<option
value=
"deactive"
>
{% trans 'Deactive selected' %}
</option>
</div>
<option
value=
"active"
>
{% trans 'Active selected' %}
</option>
</div>
</select>
<div
class=
"col-lg-9 animated fadeInRight"
id=
"split-right"
>
<div
class=
"input-group-btn pull-left"
style=
"padding-left: 5px;"
>
<div
class=
"mail-box-header"
>
<button
id=
'btn_bulk_update'
style=
"height: 32px;"
class=
"btn btn-sm btn-primary"
>
<table
class=
"table table-striped table-bordered table-hover "
id=
"asset_list_modal_table"
style=
"width: 100%"
>
{% trans 'Submit' %}
<thead>
</button>
<tr>
<th
class=
"text-center"
><input
type=
"checkbox"
class=
"ipt_check_all"
></th>
<th
class=
"text-center"
>
{% trans 'Hostname' %}
</th>
<th
class=
"text-center"
>
{% trans 'IP' %}
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
var
modal_table
;
function
initModalTable
()
{
<script>
var
zTree2
,
asset_table2
=
0
;
function
initTable2
()
{
var
options
=
{
var
options
=
{
ele
:
$
(
'#asset_modal_table'
),
ele
:
$
(
'#asset_list_modal_table'
),
columnDefs
:
[
{
targets
:
1
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
{
%
url
'assets:asset-detail'
pk
=
DEFAULT_PK
as
the_url
%
}
var
detail_btn
=
'<a href="{{ the_url }}">'
+
cellData
+
'</a>'
;
$
(
td
).
html
(
detail_btn
.
replace
(
'{{ DEFAULT_PK }}'
,
rowData
.
id
));
}},
{
targets
:
3
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
$
(
td
).
html
(
rowData
.
hardware_info
)
}},
{
targets
:
4
,
createdCell
:
function
(
td
,
cellData
)
{
if
(
!
cellData
)
{
$
(
td
).
html
(
'<i class="fa fa-times text-danger"></i>'
)
}
else
{
$
(
td
).
html
(
'<i class="fa fa-check text-navy"></i>'
)
}
}},
{
targets
:
5
,
createdCell
:
function
(
td
,
cellData
)
{
if
(
cellData
===
'Unknown'
){
$
(
td
).
html
(
'<i class="fa fa-circle text-warning"></i>'
)
}
else
if
(
!
cellData
)
{
$
(
td
).
html
(
'<i class="fa fa-circle text-danger"></i>'
)
}
else
{
$
(
td
).
html
(
'<i class="fa fa-circle text-navy"></i>'
)
}
}},
{
targets
:
6
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
update_btn
=
'<a href="{% url "assets:asset-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'
.
replace
(
"{{ DEFAULT_PK }}"
,
cellData
);
var
del_btn
=
'<a class="btn btn-xs btn-danger m-l-xs btn_asset_delete" data-uid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
);
$
(
td
).
html
(
update_btn
+
del_btn
)
}}
],
ajax_url
:
'{% url "api-assets:asset-list" %}'
,
ajax_url
:
'{% url "api-assets:asset-list" %}'
,
columns
:
[
columns
:
[
{
data
:
"id"
},
{
data
:
"hostname"
},
{
data
:
"ip"
},
{
data
:
"id"
},
{
data
:
"hostname"
},
{
data
:
"ip"
}
{
data
:
"cpu_cores"
},
{
data
:
"is_active"
,
orderable
:
false
},
{
data
:
"is_connective"
,
orderable
:
false
},
{
data
:
"id"
,
orderable
:
false
}
],
],
op_html
:
$
(
'#actions'
).
html
()
pageLength
:
10
};
};
modal_table
=
jumpserver
.
initServerSideDataTable
(
options
);
asset_table2
=
jumpserver
.
initServerSideDataTable
(
options
);
return
modal_table
;
return
asset_table2
}
}
$
(
document
).
ready
(
function
(){
function
onSelected2
(
event
,
treeNode
)
{
initModalTable
();
var
url
=
asset_table2
.
ajax
.
url
();
}).
on
(
'click'
,
'#btn_select_assets'
,
function
()
{
url
=
setUrlParam
(
url
,
"node_id"
,
treeNode
.
id
);
var
data_table
=
$
(
'#asset_modal_table'
).
DataTable
();
setCookie
(
'node_selected'
,
treeNode
.
id
);
var
id_list
=
[];
asset_table2
.
ajax
.
url
(
url
);
data_table
.
rows
({
selected
:
true
}).
every
(
function
(){
asset_table2
.
ajax
.
reload
();
id_list
.
push
(
this
.
data
().
id
);
}
});
var
current_node
;
var
nodes
=
zTree
.
getSelectedNodes
();
if
(
nodes
&&
nodes
.
length
===
1
)
{
current_node
=
nodes
[
0
]
}
else
{
return
}
var
data
=
{
'assets'
:
id_list
};
var
success
=
function
()
{
function
initTree2
()
{
modal_table
.
ajax
.
reload
()
var
setting
=
{
view
:
{
dblClickExpand
:
false
,
showLine
:
true
},
data
:
{
simpleData
:
{
enable
:
true
}
},
callback
:
{
onSelected
:
onSelected2
}
};
};
APIUpdateAttr
({
var
zNodes
=
[];
'url'
:
'/api/assets/v1/nodes/'
+
current_node
.
id
+
'/assets/add/'
,
$
.
get
(
"{% url 'api-assets:node-list' %}"
,
function
(
data
,
status
){
'method'
:
'PUT'
,
$
.
each
(
data
,
function
(
index
,
value
)
{
'body'
:
JSON
.
stringify
(
data
),
value
[
"pId"
]
=
value
[
"parent"
];
'success'
:
success
value
[
"open"
]
=
true
;
})
value
[
"name"
]
=
value
[
"value"
]
+
' ('
+
value
[
'assets_amount'
]
+
')'
;
value
[
'value'
]
=
value
[
'value'
];
});
zNodes
=
data
;
$
.
fn
.
zTree
.
init
(
$
(
"#assetTree2"
),
setting
,
zNodes
);
zTree2
=
$
.
fn
.
zTree
.
getZTreeObj
(
"assetTree2"
);
});
}
$
(
document
).
ready
(
function
(){
initTable2
();
initTree2
();
})
})
</script>
</script>
{% endblock %}
{% block modal_button %}
{{ block.super }}
{% endblock %}
{% endblock %}
{% block modal_confirm_id %}btn_select_assets{% endblock %}
{% block modal_confirm_id %}btn_asset_modal_confirm{% endblock %}
apps/assets/templates/assets/asset_detail.html
View file @
53c532a6
...
@@ -305,9 +305,9 @@ $(document).ready(function () {
...
@@ -305,9 +305,9 @@ $(document).ready(function () {
success_message
:
success
success_message
:
success
});
});
if
(
status
===
"False"
)
{
if
(
status
===
"False"
)
{
$
(
".ibox-content > table > tbody > tr:nth-child(13) > td:last >b"
).
html
(
'True'
);
$
(
".ibox-content > table > tbody > tr:nth-child(13) > td:last >b"
).
html
(
'True'
);
}
else
{
}
else
{
$
(
".ibox-content > table > tbody > tr:nth-child(13) > td:last >b"
).
html
(
'False'
);
$
(
".ibox-content > table > tbody > tr:nth-child(13) > td:last >b"
).
html
(
'False'
);
}
}
}).
on
(
'click'
,
'#btn-update-nodes'
,
function
()
{
}).
on
(
'click'
,
'#btn-update-nodes'
,
function
()
{
if
(
Object
.
keys
(
jumpserver
.
nodes_selected
).
length
===
0
)
{
if
(
Object
.
keys
(
jumpserver
.
nodes_selected
).
length
===
0
)
{
...
...
apps/assets/templates/assets/asset_list.html
View file @
53c532a6
This diff is collapsed.
Click to expand it.
apps/assets/templates/assets/domain_create_update.html
View file @
53c532a6
...
@@ -18,14 +18,25 @@
...
@@ -18,14 +18,25 @@
</div>
</div>
</div>
</div>
</form>
</form>
{% include 'assets/_asset_list_modal.html' %}
{% endblock %}
{% endblock %}
{% block custom_foot_js %}
{% block custom_foot_js %}
<script
type=
"text/javascript"
>
<script
type=
"text/javascript"
>
$
(
document
).
ready
(
function
()
{
$
(
document
).
ready
(
function
()
{
$
(
'.select2'
).
select2
({
console
.
log
(
$
.
fn
.
select2
.
defaults
);
closeOnSelect
:
false
$
(
'.select2'
).
select2
().
off
(
"select2:open"
);
});
}).
on
(
'click'
,
'.select2-selection__rendered'
,
function
(
e
)
{
e
.
preventDefault
();
$
(
"#asset_list_modal"
).
modal
();
})
.
on
(
'click'
,
'#btn_asset_modal_confirm'
,
function
()
{
var
assets
=
asset_table2
.
selected
;
$
.
each
(
assets
,
function
(
id
,
data
)
{
$
(
'.select2'
).
val
(
assets
).
trigger
(
'change'
);
});
});
$
(
"#asset_list_modal"
).
modal
(
'hide'
);
})
</script>
</script>
{% endblock %}
{% endblock %}
\ No newline at end of file
apps/assets/templates/assets/domain_gateway_list.html
View file @
53c532a6
...
@@ -81,11 +81,6 @@ function initTable() {
...
@@ -81,11 +81,6 @@ function initTable() {
var
options
=
{
var
options
=
{
ele
:
$
(
'#domain_list_table'
),
ele
:
$
(
'#domain_list_table'
),
columnDefs
:
[
columnDefs
:
[
{
targets
:
1
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
detail_btn
=
'<a href="{% url "assets:domain-detail" pk=DEFAULT_PK %}">'
+
cellData
+
'</a>'
;
$
(
td
).
html
(
detail_btn
.
replace
(
'{{ DEFAULT_PK }}'
,
rowData
.
id
));
}},
{
targets
:
7
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
{
targets
:
7
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
update_btn
=
'<a href="{% url "assets:domain-gateway-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
);
var
update_btn
=
'<a href="{% url "assets:domain-gateway-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
);
var
del_btn
=
'<a class="btn btn-xs btn-danger m-l-xs btn-delete" data-uid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
);
var
del_btn
=
'<a class="btn btn-xs btn-danger m-l-xs btn-delete" data-uid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
);
...
...
apps/assets/templates/assets/label_create_update.html
View file @
53c532a6
...
@@ -3,6 +3,8 @@
...
@@ -3,6 +3,8 @@
{% load bootstrap3 %}
{% load bootstrap3 %}
{% load i18n %}
{% load i18n %}
{% block form %}
{% block form %}
<form
id=
"groupForm"
method=
"post"
class=
"form-horizontal"
>
<form
id=
"groupForm"
method=
"post"
class=
"form-horizontal"
>
{% csrf_token %}
{% csrf_token %}
...
@@ -18,14 +20,28 @@
...
@@ -18,14 +20,28 @@
</div>
</div>
</div>
</div>
</form>
</form>
{% include 'assets/_asset_list_modal.html' %}
{% endblock %}
{% endblock %}
{% block custom_foot_js %}
{% block custom_foot_js %}
<script
type=
"text/javascript"
>
<script
type=
"text/javascript"
>
$
(
document
).
ready
(
function
()
{
$
(
document
).
ready
(
function
()
{
$
(
'.select2'
).
select2
({
$
(
'.select2'
).
select2
({
closeOnSelect
:
false
closeOnSelect
:
false
});
})
}).
on
(
'click'
,
'.select2-selection__rendered'
,
function
(
e
)
{
e
.
preventDefault
();
$
(
"#asset_list_modal"
).
modal
();
})
.
on
(
'click'
,
'#btn_asset_modal_confirm'
,
function
()
{
var
assets
=
asset_table2
.
selected
;
$
(
'.select2 option:selected'
).
each
(
function
(
i
,
data
)
{
assets
.
push
(
$
(
data
).
attr
(
'value'
))
});
$
.
each
(
assets
,
function
(
id
,
data
)
{
$
(
'.select2'
).
val
(
assets
).
trigger
(
'change'
);
});
});
$
(
"#asset_list_modal"
).
modal
(
'hide'
);
})
</script>
</script>
{% endblock %}
{% endblock %}
\ No newline at end of file
apps/assets/templates/assets/system_user_detail.html
View file @
53c532a6
...
@@ -173,7 +173,7 @@
...
@@ -173,7 +173,7 @@
<td
colspan=
"2"
class=
"no-borders"
>
<td
colspan=
"2"
class=
"no-borders"
>
<select
data-placeholder=
"{% trans 'Add to node' %}"
id=
"node_selected"
class=
"select2"
style=
"width: 100%"
multiple=
""
tabindex=
"4"
>
<select
data-placeholder=
"{% trans 'Add to node' %}"
id=
"node_selected"
class=
"select2"
style=
"width: 100%"
multiple=
""
tabindex=
"4"
>
{% for node in nodes_remain %}
{% for node in nodes_remain %}
<option
value=
"{{ node.id }}"
id=
"opt_{{ node.id }}"
>
{{ node
.name
}}
</option>
<option
value=
"{{ node.id }}"
id=
"opt_{{ node.id }}"
>
{{ node }}
</option>
{% endfor %}
{% endfor %}
</select>
</select>
</td>
</td>
...
@@ -187,7 +187,7 @@
...
@@ -187,7 +187,7 @@
{% for node in system_user.nodes.all %}
{% for node in system_user.nodes.all %}
<tr>
<tr>
<td
><b
class=
"bdg_node"
data-gid=
{{
node
.
id
}}
>
{{ node
.name
}}
</b></td>
<td
><b
class=
"bdg_node"
data-gid=
{{
node
.
id
}}
>
{{ node }}
</b></td>
<td>
<td>
<button
class=
"btn btn-danger pull-right btn-xs btn-remove-from-node"
type=
"button"
><i
class=
"fa fa-minus"
></i></button>
<button
class=
"btn btn-danger pull-right btn-xs btn-remove-from-node"
type=
"button"
><i
class=
"fa fa-minus"
></i></button>
</td>
</td>
...
...
apps/assets/urls/api_urls.py
View file @
53c532a6
...
@@ -40,6 +40,7 @@ urlpatterns = [
...
@@ -40,6 +40,7 @@ urlpatterns = [
url
(
r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/children/add/$'
,
api
.
NodeAddChildrenApi
.
as_view
(),
name
=
'node-add-children'
),
url
(
r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/children/add/$'
,
api
.
NodeAddChildrenApi
.
as_view
(),
name
=
'node-add-children'
),
url
(
r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$'
,
api
.
NodeAssetsApi
.
as_view
(),
name
=
'node-assets'
),
url
(
r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$'
,
api
.
NodeAssetsApi
.
as_view
(),
name
=
'node-assets'
),
url
(
r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/add/$'
,
api
.
NodeAddAssetsApi
.
as_view
(),
name
=
'node-add-assets'
),
url
(
r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/add/$'
,
api
.
NodeAddAssetsApi
.
as_view
(),
name
=
'node-add-assets'
),
url
(
r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/replace/$'
,
api
.
NodeReplaceAssetsApi
.
as_view
(),
name
=
'node-replace-assets'
),
url
(
r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/remove/$'
,
api
.
NodeRemoveAssetsApi
.
as_view
(),
name
=
'node-remove-assets'
),
url
(
r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/remove/$'
,
api
.
NodeRemoveAssetsApi
.
as_view
(),
name
=
'node-remove-assets'
),
url
(
r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/refresh-hardware-info/$'
,
api
.
RefreshNodeHardwareInfoApi
.
as_view
(),
name
=
'node-refresh-hardware-info'
),
url
(
r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/refresh-hardware-info/$'
,
api
.
RefreshNodeHardwareInfoApi
.
as_view
(),
name
=
'node-refresh-hardware-info'
),
url
(
r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/test-connective/$'
,
api
.
TestNodeConnectiveApi
.
as_view
(),
name
=
'node-test-connective'
),
url
(
r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/test-connective/$'
,
api
.
TestNodeConnectiveApi
.
as_view
(),
name
=
'node-test-connective'
),
...
...
apps/assets/views/asset.py
View file @
53c532a6
...
@@ -49,6 +49,7 @@ class AssetListView(AdminUserRequiredMixin, TemplateView):
...
@@ -49,6 +49,7 @@ class AssetListView(AdminUserRequiredMixin, TemplateView):
'app'
:
_
(
'Assets'
),
'app'
:
_
(
'Assets'
),
'action'
:
_
(
'Asset list'
),
'action'
:
_
(
'Asset list'
),
'labels'
:
Label
.
objects
.
all
()
.
order_by
(
'name'
),
'labels'
:
Label
.
objects
.
all
()
.
order_by
(
'name'
),
'nodes'
:
Node
.
objects
.
all
()
.
order_by
(
'-key'
),
}
}
kwargs
.
update
(
context
)
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
return
super
()
.
get_context_data
(
**
kwargs
)
...
@@ -284,24 +285,26 @@ class BulkImportAssetView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
...
@@ -284,24 +285,26 @@ class BulkImportAssetView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
if
set
(
row
)
==
{
''
}:
if
set
(
row
)
==
{
''
}:
continue
continue
asset_dict
=
dict
(
zip
(
attr
,
row
))
asset_dict
_raw
=
dict
(
zip
(
attr
,
row
))
id_
=
asset_dict
.
pop
(
'id'
,
0
)
asset_dict
=
dict
(
)
for
k
,
v
in
asset_dict
.
items
():
for
k
,
v
in
asset_dict
_raw
.
items
():
v
=
v
.
strip
()
v
=
v
.
strip
()
if
k
==
'is_active'
:
if
k
==
'is_active'
:
v
=
True
if
v
in
[
'TRUE'
,
1
,
'true'
]
else
Fals
e
v
=
False
if
v
in
[
'False'
,
0
,
'false'
]
else
Tru
e
elif
k
==
'admin_user'
:
elif
k
==
'admin_user'
:
v
=
get_object_or_none
(
AdminUser
,
name
=
v
)
v
=
get_object_or_none
(
AdminUser
,
name
=
v
)
elif
k
in
[
'port'
,
'cpu_count'
,
'cpu_cores'
]:
elif
k
in
[
'port'
,
'cpu_count'
,
'cpu_cores'
]:
try
:
try
:
v
=
int
(
v
)
v
=
int
(
v
)
except
ValueError
:
except
ValueError
:
v
=
0
v
=
''
elif
k
==
'domain'
:
elif
k
==
'domain'
:
v
=
get_object_or_none
(
Domain
,
name
=
v
)
v
=
get_object_or_none
(
Domain
,
name
=
v
)
asset_dict
[
k
]
=
v
asset
=
get_object_or_none
(
Asset
,
id
=
id_
)
if
is_uuid
(
id_
)
else
None
if
v
!=
''
:
asset_dict
[
k
]
=
v
asset
=
get_object_or_none
(
Asset
,
id
=
asset_dict
.
pop
(
'id'
,
0
))
if
not
asset
:
if
not
asset
:
try
:
try
:
if
len
(
Asset
.
objects
.
filter
(
hostname
=
asset_dict
.
get
(
'hostname'
))):
if
len
(
Asset
.
objects
.
filter
(
hostname
=
asset_dict
.
get
(
'hostname'
))):
...
@@ -316,7 +319,7 @@ class BulkImportAssetView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
...
@@ -316,7 +319,7 @@ class BulkImportAssetView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
failed
.
append
(
'
%
s:
%
s'
%
(
asset_dict
[
'hostname'
],
str
(
e
)))
failed
.
append
(
'
%
s:
%
s'
%
(
asset_dict
[
'hostname'
],
str
(
e
)))
else
:
else
:
for
k
,
v
in
asset_dict
.
items
():
for
k
,
v
in
asset_dict
.
items
():
if
v
:
if
v
!=
''
:
setattr
(
asset
,
k
,
v
)
setattr
(
asset
,
k
,
v
)
try
:
try
:
asset
.
save
()
asset
.
save
()
...
...
apps/common/fields.py
View file @
53c532a6
...
@@ -2,11 +2,15 @@
...
@@ -2,11 +2,15 @@
#
#
import
json
import
json
from
django.db
import
models
from
django
import
forms
from
django
import
forms
from
django.utils
import
six
from
django.utils
import
six
from
django.core.exceptions
import
ValidationError
from
django.core.exceptions
import
ValidationError
from
django.utils.translation
import
ugettext
as
_
from
django.utils.translation
import
ugettext
as
_
from
rest_framework
import
serializers
from
rest_framework
import
serializers
from
.utils
import
get_signer
signer
=
get_signer
()
class
DictField
(
forms
.
Field
):
class
DictField
(
forms
.
Field
):
...
@@ -46,4 +50,27 @@ class StringIDField(serializers.Field):
...
@@ -46,4 +50,27 @@ class StringIDField(serializers.Field):
class
StringManyToManyField
(
serializers
.
RelatedField
):
class
StringManyToManyField
(
serializers
.
RelatedField
):
def
to_representation
(
self
,
value
):
def
to_representation
(
self
,
value
):
return
value
.
__str__
()
return
value
.
__str__
()
\ No newline at end of file
class
EncryptMixin
:
def
from_db_value
(
self
,
value
,
expression
,
connection
,
context
):
if
value
is
not
None
:
return
signer
.
unsign
(
value
)
return
super
()
.
from_db_value
(
self
,
value
,
expression
,
connection
,
context
)
def
get_prep_value
(
self
,
value
):
if
value
is
None
:
return
value
return
signer
.
sign
(
value
)
.
decode
(
'utf-8'
)
class
EncryptTextField
(
EncryptMixin
,
models
.
TextField
):
description
=
_
(
"Encrypt field using Secret Key"
)
class
EncryptCharField
(
EncryptMixin
,
models
.
CharField
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
kwargs
[
'max_length'
]
=
2048
super
()
.
__init__
(
*
args
,
**
kwargs
)
apps/i18n/zh/LC_MESSAGES/django.mo
View file @
53c532a6
No preview for this file type
apps/i18n/zh/LC_MESSAGES/django.po
View file @
53c532a6
This diff is collapsed.
Click to expand it.
apps/jumpserver/urls.py
View file @
53c532a6
...
@@ -36,9 +36,10 @@ urlpatterns = [
...
@@ -36,9 +36,10 @@ urlpatterns = [
url
(
r'^captcha/'
,
include
(
'captcha.urls'
)),
url
(
r'^captcha/'
,
include
(
'captcha.urls'
)),
]
]
urlpatterns
+=
static
(
settings
.
MEDIA_URL
,
document_root
=
settings
.
MEDIA_ROOT
)
\
+
static
(
settings
.
STATIC_URL
,
document_root
=
settings
.
STATIC_ROOT
)
if
settings
.
DEBUG
:
if
settings
.
DEBUG
:
urlpatterns
+=
[
urlpatterns
+=
[
url
(
r'^docs/'
,
schema_view
,
name
=
"docs"
),
url
(
r'^docs/'
,
schema_view
,
name
=
"docs"
),
]
+
static
(
settings
.
STATIC_URL
,
document_root
=
settings
.
STATIC_ROOT
)
\
]
+
static
(
settings
.
MEDIA_URL
,
document_root
=
settings
.
MEDIA_ROOT
)
apps/perms/templates/perms/asset_permission_asset.html
View file @
53c532a6
...
@@ -85,9 +85,9 @@
...
@@ -85,9 +85,9 @@
<form>
<form>
<tr
class=
"no-borders-tr"
>
<tr
class=
"no-borders-tr"
>
<td
colspan=
"2"
>
<td
colspan=
"2"
>
<select
data-placeholder=
"{% trans 'Select assets' %}"
class=
"select2
asset
"
style=
"width: 100%"
multiple=
""
tabindex=
"4"
>
<select
data-placeholder=
"{% trans 'Select assets' %}"
class=
"select2
"
id=
"asset_select2
"
style=
"width: 100%"
multiple=
""
tabindex=
"4"
>
{% for asset in assets_remain %}
{% for asset in assets_remain %}
<option
value=
"{{ asset.id }}"
>
{{ asset
.hostname
}}
</option>
<option
value=
"{{ asset.id }}"
>
{{ asset }}
</option>
{% endfor %}
{% endfor %}
</select>
</select>
</td>
</td>
...
@@ -113,9 +113,9 @@
...
@@ -113,9 +113,9 @@
<form>
<form>
<tr>
<tr>
<td
colspan=
"2"
class=
"no-borders"
>
<td
colspan=
"2"
class=
"no-borders"
>
<select
data-placeholder=
"{% trans 'Select nodes' %}"
class=
"select2
group
"
style=
"width: 100%"
multiple=
""
tabindex=
"4"
>
<select
data-placeholder=
"{% trans 'Select nodes' %}"
class=
"select2
"
id=
"node_select2
"
style=
"width: 100%"
multiple=
""
tabindex=
"4"
>
{% for node in nodes_remain %}
{% for node in nodes_remain %}
<option
value=
"{{ node.id }}"
id=
"opt_{{ node.id }}"
>
{{ node
.value
}}
</option>
<option
value=
"{{ node.id }}"
id=
"opt_{{ node.id }}"
>
{{ node }}
</option>
{% endfor %}
{% endfor %}
</select>
</select>
</td>
</td>
...
@@ -129,9 +129,9 @@
...
@@ -129,9 +129,9 @@
{% for node in asset_permission.nodes.all %}
{% for node in asset_permission.nodes.all %}
<tr>
<tr>
<td
><b
class=
"bdg_
user_group"
data-gid=
{{
node
.
id
}}
>
{{ node.valu
e }}
</b></td>
<td
><b
class=
"bdg_
group"
data-gid=
{{
node
.
id
}}
>
{{ nod
e }}
</b></td>
<td>
<td>
<button
class=
"btn btn-danger btn-xs btn-remove-node"
type=
"button"
style=
"float: right;"
><i
class=
"fa fa-minus"
></i></button>
<button
class=
"btn btn-danger btn-xs btn-remove-node"
type=
"button"
data-gid=
"{{ node.id }}"
style=
"float: right;"
><i
class=
"fa fa-minus"
></i></button>
</td>
</td>
</tr>
</tr>
{% endfor %}
{% endfor %}
...
@@ -179,49 +179,30 @@ function removeAssets(assets) {
...
@@ -179,49 +179,30 @@ function removeAssets(assets) {
});
});
}
}
function
updateNodes
(
nodes
)
{
function
updateNodes
(
nodes
,
success
)
{
var
the_url
=
"{% url 'api-perms:asset-permission-detail' pk=asset_permission.id %}"
;
var
the_url
=
"{% url 'api-perms:asset-permission-detail' pk=asset_permission.id %}"
;
var
body
=
{
var
body
=
{
nodes
:
nodes
nodes
:
nodes
};
};
APIUpdateAttr
({
APIUpdateAttr
({
url
:
the_url
,
url
:
the_url
,
body
:
JSON
.
stringify
(
body
)
body
:
JSON
.
stringify
(
body
),
success
:
success
});
});
}
}
jumpserver
.
assets_selected
=
{};
jumpserver
.
nodes_selected
=
{};
$
(
document
).
ready
(
function
()
{
$
(
document
).
ready
(
function
()
{
$
(
'.select2.asset'
).
select2
()
$
(
'.select2'
).
select2
();
.
on
(
'select2:select'
,
function
(
evt
)
{
var
data
=
evt
.
params
.
data
;
jumpserver
.
assets_selected
[
data
.
id
]
=
data
.
text
;
})
.
on
(
'select2:unselect'
,
function
(
evt
)
{
var
data
=
evt
.
params
.
data
;
delete
jumpserver
.
assets_selected
[
data
.
id
]
});
$
(
'.select2.group'
).
select2
()
.
on
(
'select2:select'
,
function
(
evt
)
{
var
data
=
evt
.
params
.
data
;
jumpserver
.
nodes_selected
[
data
.
id
]
=
data
.
text
;
})
.
on
(
'select2:unselect'
,
function
(
evt
)
{
var
data
=
evt
.
params
.
data
;
delete
jumpserver
.
nodes_selected
[
data
.
id
]
})
})
})
.
on
(
'click'
,
'.btn-add-assets'
,
function
()
{
.
on
(
'click'
,
'.btn-add-assets'
,
function
()
{
if
(
Object
.
keys
(
jumpserver
.
assets_selected
).
length
===
0
)
{
var
assets_selected
=
$
(
"#asset_select2 option:selected"
).
map
(
function
()
{
return
$
(
this
).
attr
(
'value'
);
}).
get
();
if
(
assets_selected
.
length
===
0
)
{
return
false
;
return
false
;
}
}
var
assets
=
[];
addAssets
(
assets_selected
);
$
.
map
(
jumpserver
.
assets_selected
,
function
(
value
,
index
)
{
assets
.
push
(
index
);
});
addAssets
(
assets
);
})
})
.
on
(
'click'
,
'.btn-remove-asset'
,
function
()
{
.
on
(
'click'
,
'.btn-remove-asset'
,
function
()
{
var
asset_id
=
$
(
this
).
data
(
"gid"
);
var
asset_id
=
$
(
this
).
data
(
"gid"
);
...
@@ -232,26 +213,30 @@ $(document).ready(function () {
...
@@ -232,26 +213,30 @@ $(document).ready(function () {
removeAssets
(
assets
)
removeAssets
(
assets
)
})
})
.
on
(
'click'
,
'#btn-add-node'
,
function
()
{
.
on
(
'click'
,
'#btn-add-node'
,
function
()
{
if
(
Object
.
keys
(
jumpserver
.
nodes_selected
).
length
===
0
)
{
var
nodes_selected
=
{};
$
(
"#node_select2 option:selected"
).
each
(
function
(
i
,
data
)
{
nodes_selected
[
$
(
data
).
attr
(
'value'
)]
=
$
(
data
).
text
();
});
if
(
Object
.
keys
(
nodes_selected
).
length
===
0
)
{
return
false
;
return
false
;
}
}
var
nodes_origin
=
$
(
'.bdg_group'
).
map
(
function
()
{
var
nodes
=
$
(
'.bdg_group'
).
map
(
function
()
{
return
$
(
this
).
data
(
'gid'
);
return
$
(
this
).
data
(
'gid'
);
}).
get
();
}).
get
();
$
.
map
(
jumpserver
.
nodes_selected
,
function
(
group_name
,
index
)
{
var
nodes
=
nodes_origin
.
concat
(
Object
.
keys
(
nodes_selected
));
nodes
.
push
(
index
);
var
success
=
function
()
{
$
(
'#opt_'
+
index
).
remove
();
$
.
map
(
nodes_selected
,
function
(
name
,
id
)
{
$
(
'.group_edit tbody'
).
append
(
$
(
'#opt_'
+
id
).
remove
();
'<tr>'
+
$
(
'.group_edit tbody'
).
append
(
'<td><b class="bdg_group" data-gid="'
+
index
+
'">'
+
group_name
+
'</b></td>'
+
'<tr>'
+
'<td><button class="btn btn-danger btn-xs pull-right btn-leave-group" type="button"><i class="fa fa-minus"></i></button></td>'
+
'<td><b class="bdg_group" data-gid="'
+
id
+
'">'
+
name
+
'</b></td>'
+
'</tr>'
'<td><button class="btn btn-danger btn-xs pull-right btn-leave-group" type="button"><i class="fa fa-minus"></i></button></td>'
+
)
'</tr>'
});
)
});
updateNodes
(
nodes
);
};
updateNodes
(
nodes
,
success
);
})
})
.
on
(
'click'
,
'.btn-remove-node'
,
function
()
{
.
on
(
'click'
,
'.btn-remove-node'
,
function
()
{
var
$this
=
$
(
this
);
var
$this
=
$
(
this
);
...
@@ -261,8 +246,10 @@ $(document).ready(function () {
...
@@ -261,8 +246,10 @@ $(document).ready(function () {
return
$
(
this
).
data
(
'gid'
);
return
$
(
this
).
data
(
'gid'
);
}
}
}).
get
();
}).
get
();
updateNodes
(
nodes
);
var
success
=
function
()
{
$tr
.
remove
()
$tr
.
remove
()
};
updateNodes
(
nodes
,
success
);
})
})
</script>
</script>
{% endblock %}
{% endblock %}
apps/perms/templates/perms/asset_permission_create_update.html
View file @
53c532a6
...
@@ -76,20 +76,37 @@
...
@@ -76,20 +76,37 @@
</div>
</div>
</div>
</div>
</div>
</div>
{% include 'assets/_asset_list_modal.html' %}
{% endblock %}
{% endblock %}
{% block custom_foot_js %}
{% block custom_foot_js %}
<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
()
{
$
(
'.select2'
).
select2
();
$
(
'.select2'
).
select2
({
$
(
'#datepicker'
).
datepicker
({
closeOnSelect
:
false
format
:
"yyyy-mm-dd"
,
});
todayBtn
:
"linked"
,
$
(
'#datepicker'
).
datepicker
({
keyboardNavigation
:
false
,
format
:
"yyyy-mm-dd"
,
forceParse
:
false
,
todayBtn
:
"linked"
,
calendarWeeks
:
true
,
keyboardNavigation
:
false
,
autoclose
:
true
forceParse
:
false
,
});
calendarWeeks
:
true
,
})
autoclose
:
true
</script>
});
$
(
"#id_assets"
).
parent
().
find
(
".select2-selection"
).
on
(
'click'
,
function
(
e
)
{
e
.
preventDefault
();
$
(
"#asset_list_modal"
).
modal
();
})
})
.
on
(
'click'
,
'#btn_asset_modal_confirm'
,
function
()
{
var
assets
=
asset_table2
.
selected
;
$
(
'.select2 option:selected'
).
each
(
function
(
i
,
data
)
{
assets
.
push
(
$
(
data
).
attr
(
'value'
))
});
$
.
each
(
assets
,
function
(
id
,
data
)
{
$
(
'.select2'
).
val
(
assets
).
trigger
(
'change'
);
});
$
(
"#asset_list_modal"
).
modal
(
'hide'
);
})
</script>
{% endblock %}
{% endblock %}
\ No newline at end of file
apps/perms/templates/perms/asset_permission_detail.html
View file @
53c532a6
...
@@ -147,7 +147,7 @@
...
@@ -147,7 +147,7 @@
<td
colspan=
"2"
>
<td
colspan=
"2"
>
<select
data-placeholder=
"{% trans 'Select system users' %}"
class=
"select2"
style=
"width: 100%"
multiple=
""
tabindex=
"4"
>
<select
data-placeholder=
"{% trans 'Select system users' %}"
class=
"select2"
style=
"width: 100%"
multiple=
""
tabindex=
"4"
>
{% for system_user in system_users_remain %}
{% for system_user in system_users_remain %}
<option
value=
"{{ system_user.id }}"
id=
"opt_{{ system_user.id }}"
>
{{ system_user
.name
}}
</option>
<option
value=
"{{ system_user.id }}"
id=
"opt_{{ system_user.id }}"
>
{{ system_user }}
</option>
{% endfor %}
{% endfor %}
</select>
</select>
</td>
</td>
...
@@ -161,7 +161,7 @@
...
@@ -161,7 +161,7 @@
{% for system_user in object.system_users.all %}
{% for system_user in object.system_users.all %}
<tr
{%
if
forloop
.
counter =
=
1
%}
class=
"no-borders-tr"
{%
endif
%}
>
<tr
{%
if
forloop
.
counter =
=
1
%}
class=
"no-borders-tr"
{%
endif
%}
>
<td
><b
class=
"bdg-system-user"
data-uid=
{{
system_user
.
id
}}
>
{{ system_user
.name
}}
</b></td>
<td
><b
class=
"bdg-system-user"
data-uid=
{{
system_user
.
id
}}
>
{{ system_user }}
</b></td>
<td>
<td>
<button
class=
"btn btn-danger btn-xs btn-remove-user"
data-uid=
"{{ system_user.id }}"
type=
"button"
style=
"float: right;"
><i
class=
"fa fa-minus"
></i></button>
<button
class=
"btn btn-danger btn-xs btn-remove-user"
data-uid=
"{{ system_user.id }}"
type=
"button"
style=
"float: right;"
><i
class=
"fa fa-minus"
></i></button>
</td>
</td>
...
...
apps/perms/templates/perms/asset_permission_user.html
View file @
53c532a6
...
@@ -87,7 +87,7 @@
...
@@ -87,7 +87,7 @@
<td
colspan=
"2"
>
<td
colspan=
"2"
>
<select
data-placeholder=
"{% trans 'Select user' %}"
class=
"select2 user"
style=
"width: 100%"
multiple=
""
tabindex=
"4"
>
<select
data-placeholder=
"{% trans 'Select user' %}"
class=
"select2 user"
style=
"width: 100%"
multiple=
""
tabindex=
"4"
>
{% for user in users_remain %}
{% for user in users_remain %}
<option
value=
"{{ user.id }}"
>
{{ user
.name
}}
</option>
<option
value=
"{{ user.id }}"
>
{{ user }}
</option>
{% endfor %}
{% endfor %}
</select>
</select>
</td>
</td>
...
@@ -115,7 +115,7 @@
...
@@ -115,7 +115,7 @@
<td
colspan=
"2"
class=
"no-borders"
>
<td
colspan=
"2"
class=
"no-borders"
>
<select
data-placeholder=
"{% trans 'Select user groups' %}"
class=
"select2 user-group"
style=
"width: 100%"
multiple=
""
tabindex=
"4"
>
<select
data-placeholder=
"{% trans 'Select user groups' %}"
class=
"select2 user-group"
style=
"width: 100%"
multiple=
""
tabindex=
"4"
>
{% for user_group in user_groups_remain %}
{% for user_group in user_groups_remain %}
<option
value=
"{{ user_group.id }}"
id=
"opt_{{ user_group.id }}"
>
{{ user_group
.name
}}
</option>
<option
value=
"{{ user_group.id }}"
id=
"opt_{{ user_group.id }}"
>
{{ user_group }}
</option>
{% endfor %}
{% endfor %}
</select>
</select>
</td>
</td>
...
@@ -129,7 +129,7 @@
...
@@ -129,7 +129,7 @@
{% for user_group in asset_permission.user_groups.all %}
{% for user_group in asset_permission.user_groups.all %}
<tr>
<tr>
<td
><b
class=
"bdg_group"
data-gid=
{{
user_group
.
id
}}
>
{{ user_group
.name
}}
</b></td>
<td
><b
class=
"bdg_group"
data-gid=
{{
user_group
.
id
}}
>
{{ user_group }}
</b></td>
<td>
<td>
<button
class=
"btn btn-danger btn-xs btn-remove-group"
type=
"button"
data-gid=
"{{ user_group.id }}"
style=
"float: right;"
><i
class=
"fa fa-minus"
></i></button>
<button
class=
"btn btn-danger btn-xs btn-remove-group"
type=
"button"
data-gid=
"{{ user_group.id }}"
style=
"float: right;"
><i
class=
"fa fa-minus"
></i></button>
</td>
</td>
...
...
apps/perms/views.py
View file @
53c532a6
...
@@ -112,7 +112,7 @@ class AssetPermissionUserView(AdminUserRequiredMixin,
...
@@ -112,7 +112,7 @@ class AssetPermissionUserView(AdminUserRequiredMixin,
return
super
()
.
get
(
request
,
*
args
,
**
kwargs
)
return
super
()
.
get
(
request
,
*
args
,
**
kwargs
)
def
get_queryset
(
self
):
def
get_queryset
(
self
):
queryset
=
self
.
object
.
get_all_users
(
)
queryset
=
list
(
self
.
object
.
get_all_users
()
)
return
queryset
return
queryset
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
...
@@ -142,7 +142,7 @@ class AssetPermissionAssetView(AdminUserRequiredMixin,
...
@@ -142,7 +142,7 @@ class AssetPermissionAssetView(AdminUserRequiredMixin,
return
super
()
.
get
(
request
,
*
args
,
**
kwargs
)
return
super
()
.
get
(
request
,
*
args
,
**
kwargs
)
def
get_queryset
(
self
):
def
get_queryset
(
self
):
queryset
=
self
.
object
.
get_all_assets
(
)
queryset
=
list
(
self
.
object
.
get_all_assets
()
)
return
queryset
return
queryset
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
...
...
apps/static/js/jumpserver.js
View file @
53c532a6
...
@@ -307,7 +307,7 @@ jumpserver.initDataTable = function (options) {
...
@@ -307,7 +307,7 @@ jumpserver.initDataTable = function (options) {
last
:
"»"
last
:
"»"
}
}
},
},
lengthMenu
:
[[
1
5
,
25
,
50
,
-
1
],
[
15
,
25
,
50
,
"All"
]]
lengthMenu
:
[[
1
0
,
15
,
25
,
50
,
-
1
],
[
10
,
15
,
25
,
50
,
"All"
]]
});
});
table
.
on
(
'select'
,
function
(
e
,
dt
,
type
,
indexes
)
{
table
.
on
(
'select'
,
function
(
e
,
dt
,
type
,
indexes
)
{
var
$node
=
table
[
type
](
indexes
).
nodes
().
to$
();
var
$node
=
table
[
type
](
indexes
).
nodes
().
to$
();
...
@@ -446,22 +446,56 @@ jumpserver.initServerSideDataTable = function (options) {
...
@@ -446,22 +446,56 @@ jumpserver.initServerSideDataTable = function (options) {
last
:
"»"
last
:
"»"
}
}
},
},
lengthMenu
:
[[
1
5
,
25
,
50
],
[
15
,
25
,
50
]]
lengthMenu
:
[[
1
0
,
15
,
25
,
50
],
[
10
,
15
,
25
,
50
]]
});
});
table
.
selected
=
[];
table
.
on
(
'select'
,
function
(
e
,
dt
,
type
,
indexes
)
{
table
.
on
(
'select'
,
function
(
e
,
dt
,
type
,
indexes
)
{
var
$node
=
table
[
type
](
indexes
).
nodes
().
to$
();
var
$node
=
table
[
type
](
indexes
).
nodes
().
to$
();
$node
.
find
(
'input.ipt_check'
).
prop
(
'checked'
,
true
);
$node
.
find
(
'input.ipt_check'
).
prop
(
'checked'
,
true
);
jumpserver
.
selected
[
$node
.
find
(
'input.ipt_check'
).
prop
(
'id'
)]
=
true
jumpserver
.
selected
[
$node
.
find
(
'input.ipt_check'
).
prop
(
'id'
)]
=
true
;
if
(
type
===
'row'
)
{
var
rows
=
table
.
rows
(
indexes
).
data
();
$
.
each
(
rows
,
function
(
id
,
row
)
{
if
(
row
.
id
){
table
.
selected
.
push
(
row
.
id
)
}
})
}
}).
on
(
'deselect'
,
function
(
e
,
dt
,
type
,
indexes
)
{
}).
on
(
'deselect'
,
function
(
e
,
dt
,
type
,
indexes
)
{
var
$node
=
table
[
type
](
indexes
).
nodes
().
to$
();
var
$node
=
table
[
type
](
indexes
).
nodes
().
to$
();
$node
.
find
(
'input.ipt_check'
).
prop
(
'checked'
,
false
);
$node
.
find
(
'input.ipt_check'
).
prop
(
'checked'
,
false
);
jumpserver
.
selected
[
$node
.
find
(
'input.ipt_check'
).
prop
(
'id'
)]
=
false
jumpserver
.
selected
[
$node
.
find
(
'input.ipt_check'
).
prop
(
'id'
)]
=
false
;
if
(
type
===
'row'
)
{
var
rows
=
table
.
rows
(
indexes
).
data
();
$
.
each
(
rows
,
function
(
id
,
row
)
{
if
(
row
.
id
){
var
index
=
table
.
selected
.
indexOf
(
row
.
id
);
if
(
index
>
-
1
){
table
.
selected
.
splice
(
index
,
1
)
}
}
})
}
}).
}).
on
(
'draw'
,
function
(){
on
(
'draw'
,
function
(){
$
(
'#op'
).
html
(
options
.
op_html
||
''
);
$
(
'#op'
).
html
(
options
.
op_html
||
''
);
$
(
'#uc'
).
html
(
options
.
uc_html
||
''
);
$
(
'#uc'
).
html
(
options
.
uc_html
||
''
);
var
table_data
=
[];
$
.
each
(
table
.
rows
().
data
(),
function
(
id
,
row
)
{
if
(
row
.
id
)
{
table_data
.
push
(
row
.
id
)
}
});
$
.
each
(
table
.
selected
,
function
(
id
,
data
)
{
var
index
=
table_data
.
indexOf
(
data
);
if
(
index
>
-
1
){
table
.
rows
(
index
).
select
()
}
});
});
});
$
(
'.ipt_check_all'
).
on
(
'click'
,
function
()
{
var
table_id
=
table
.
settings
()[
0
].
sTableId
;
$
(
'#'
+
table_id
+
' .ipt_check_all'
).
on
(
'click'
,
function
()
{
if
(
$
(
this
).
prop
(
"checked"
))
{
if
(
$
(
this
).
prop
(
"checked"
))
{
$
(
this
).
closest
(
'table'
).
find
(
'.ipt_check'
).
prop
(
'checked'
,
true
);
$
(
this
).
closest
(
'table'
).
find
(
'.ipt_check'
).
prop
(
'checked'
,
true
);
table
.
rows
({
search
:
'applied'
,
page
:
'current'
}).
select
();
table
.
rows
({
search
:
'applied'
,
page
:
'current'
}).
select
();
...
...
apps/templates/_modal.html
View file @
53c532a6
{% load i18n %}
{% load i18n %}
<style>
.modal-body
{
padding
:
0px
20px
0px
20px
;
}
</style>
<div
aria-hidden=
"true"
role=
"dialog"
id=
"{% block modal_id %}{% endblock %}"
class=
"modal inmodal"
>
<div
aria-hidden=
"true"
role=
"dialog"
id=
"{% block modal_id %}{% endblock %}"
class=
"modal inmodal"
>
<div
class=
"modal-dialog {% block modal_class %}{% endblock %}"
>
<div
class=
"modal-dialog {% block modal_class %}{% endblock %}"
>
<div
class=
"modal-content animated fadeIn"
>
<div
class=
"modal-content animated fadeIn"
>
...
@@ -12,8 +17,10 @@
...
@@ -12,8 +17,10 @@
{% endblock %}
{% endblock %}
</div>
</div>
<div
class=
"modal-footer"
>
<div
class=
"modal-footer"
>
{% block modal_button %}
<button
data-dismiss=
"modal"
class=
"btn btn-white"
type=
"button"
>
{% trans "Close" %}
</button>
<button
data-dismiss=
"modal"
class=
"btn btn-white"
type=
"button"
>
{% trans "Close" %}
</button>
<button
class=
"btn btn-primary"
type=
"button"
id=
"{% block modal_confirm_id %}{% endblock %}"
>
{% trans 'Confirm' %}
</button>
<button
class=
"btn btn-primary"
type=
"button"
id=
"{% block modal_confirm_id %}{% endblock %}"
>
{% trans 'Confirm' %}
</button>
{% endblock %}
</div>
</div>
</div>
</div>
</div>
</div>
...
...
apps/templates/_nav.html
View file @
53c532a6
...
@@ -61,7 +61,7 @@
...
@@ -61,7 +61,7 @@
</li>
</li>
<li
id=
"audits"
>
<li
id=
"audits"
>
<a>
<a>
<i
class=
"fa fa-
coffee
"
style=
"width: 14px"
></i>
<span
class=
"nav-label"
>
{% trans 'Audits' %}
</span><span
class=
"fa arrow"
></span>
<i
class=
"fa fa-
history
"
style=
"width: 14px"
></i>
<span
class=
"nav-label"
>
{% trans 'Audits' %}
</span><span
class=
"fa arrow"
></span>
</a>
</a>
<ul
class=
"nav nav-second-level"
>
<ul
class=
"nav nav-second-level"
>
<li
id=
"ftp-log"
><a
href=
"{% url 'audits:ftp-log-list' %}"
>
{% trans 'FTP log' %}
</a></li>
<li
id=
"ftp-log"
><a
href=
"{% url 'audits:ftp-log-list' %}"
>
{% trans 'FTP log' %}
</a></li>
...
...
apps/terminal/api.py
View file @
53c532a6
...
@@ -248,7 +248,7 @@ class CommandViewSet(viewsets.ViewSet):
...
@@ -248,7 +248,7 @@ class CommandViewSet(viewsets.ViewSet):
class
SessionReplayViewSet
(
viewsets
.
ViewSet
):
class
SessionReplayViewSet
(
viewsets
.
ViewSet
):
serializer_class
=
ReplaySerializer
serializer_class
=
ReplaySerializer
permission_classes
=
()
permission_classes
=
(
IsSuperUserOrAppUser
,
)
session
=
None
session
=
None
def
gen_session_path
(
self
):
def
gen_session_path
(
self
):
...
...
apps/users/models/user.py
View file @
53c532a6
...
@@ -45,7 +45,7 @@ class User(AbstractUser):
...
@@ -45,7 +45,7 @@ class User(AbstractUser):
wechat
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
verbose_name
=
_
(
'Wechat'
))
wechat
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
verbose_name
=
_
(
'Wechat'
))
phone
=
models
.
CharField
(
max_length
=
20
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Phone'
))
phone
=
models
.
CharField
(
max_length
=
20
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Phone'
))
otp_level
=
models
.
SmallIntegerField
(
default
=
0
,
choices
=
OTP_LEVEL_CHOICES
,
verbose_name
=
_
(
'Enable OTP'
))
otp_level
=
models
.
SmallIntegerField
(
default
=
0
,
choices
=
OTP_LEVEL_CHOICES
,
verbose_name
=
_
(
'Enable OTP'
))
otp_secret_key
=
models
.
CharField
(
max_length
=
16
,
blank
=
True
,
null
=
True
)
_otp_secret_key
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
null
=
True
)
# Todo: Auto generate key, let user download
# Todo: Auto generate key, let user download
_private_key
=
models
.
CharField
(
max_length
=
5000
,
blank
=
True
,
verbose_name
=
_
(
'Private key'
))
_private_key
=
models
.
CharField
(
max_length
=
5000
,
blank
=
True
,
verbose_name
=
_
(
'Private key'
))
_public_key
=
models
.
CharField
(
max_length
=
5000
,
blank
=
True
,
verbose_name
=
_
(
'Public key'
))
_public_key
=
models
.
CharField
(
max_length
=
5000
,
blank
=
True
,
verbose_name
=
_
(
'Public key'
))
...
@@ -70,6 +70,14 @@ class User(AbstractUser):
...
@@ -70,6 +70,14 @@ class User(AbstractUser):
def
password_raw
(
self
,
password_raw_
):
def
password_raw
(
self
,
password_raw_
):
self
.
set_password
(
password_raw_
)
self
.
set_password
(
password_raw_
)
@property
def
otp_secret_key
(
self
):
return
signer
.
unsign
(
self
.
_otp_secret_key
)
@otp_secret_key.setter
def
otp_secret_key
(
self
,
item
):
self
.
_otp_secret_key
=
signer
.
sign
(
item
)
.
decode
(
'utf-8'
)
def
get_absolute_url
(
self
):
def
get_absolute_url
(
self
):
return
reverse
(
'users:user-detail'
,
args
=
(
self
.
id
,))
return
reverse
(
'users:user-detail'
,
args
=
(
self
.
id
,))
...
...
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