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
84634eb8
Commit
84634eb8
authored
Apr 10, 2018
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Update] 修改Permr认证
parent
fffa0def
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
549 additions
and
305 deletions
+549
-305
node.py
apps/assets/api/node.py
+75
-7
node.py
apps/assets/models/node.py
+5
-0
user.py
apps/assets/models/user.py
+0
-2
node.py
apps/assets/serializers/node.py
+1
-1
tasks.py
apps/assets/tasks.py
+1
-1
api_urls.py
apps/assets/urls/api_urls.py
+2
-0
fields.py
apps/common/fields.py
+5
-0
api.py
apps/perms/api.py
+26
-0
forms.py
apps/perms/forms.py
+19
-0
models.py
apps/perms/models.py
+0
-73
serializers.py
apps/perms/serializers.py
+16
-1
asset_permission_list.html
apps/perms/templates/perms/asset_permission_list.html
+302
-141
views_urls.py
apps/perms/urls/views_urls.py
+1
-1
views.py
apps/perms/views.py
+32
-46
awesome.css
apps/static/css/plugins/ztree/awesomeStyle/awesome.css
+33
-9
awesome.less
apps/static/css/plugins/ztree/awesomeStyle/awesome.less
+21
-17
jumpserver.js
apps/static/js/jumpserver.js
+8
-2
login.py
apps/users/views/login.py
+2
-4
No files found.
apps/assets/api/node.py
View file @
84634eb8
...
...
@@ -30,6 +30,7 @@ from .. import serializers
logger
=
get_logger
(
__file__
)
__all__
=
[
'NodeViewSet'
,
'NodeChildrenApi'
,
'NodeAssetsApi'
,
'NodeWithAssetsApi'
,
'NodeAddAssetsApi'
,
'NodeRemoveAssetsApi'
,
'NodeAddChildrenApi'
,
'RefreshNodeHardwareInfoApi'
,
'TestNodeConnectiveApi'
...
...
@@ -47,6 +48,34 @@ class NodeViewSet(BulkModelViewSet):
serializer
.
save
()
class
NodeWithAssetsApi
(
generics
.
ListAPIView
):
permission_classes
=
(
IsSuperUser
,)
serializers
=
serializers
.
NodeSerializer
def
get_node
(
self
):
pk
=
self
.
kwargs
.
get
(
'pk'
)
or
self
.
request
.
query_params
.
get
(
'node'
)
if
not
pk
:
node
=
Node
.
root
()
else
:
node
=
get_object_or_404
(
Node
,
pk
)
return
node
def
get_queryset
(
self
):
queryset
=
[]
node
=
self
.
get_node
()
children
=
node
.
get_children
()
assets
=
node
.
get_assets
()
queryset
.
extend
(
list
(
children
))
for
asset
in
assets
:
node
=
Node
()
node
.
id
=
asset
.
id
node
.
parent
=
node
.
id
node
.
value
=
asset
.
hostname
queryset
.
append
(
node
)
return
queryset
class
NodeChildrenApi
(
mixins
.
ListModelMixin
,
generics
.
CreateAPIView
):
queryset
=
Node
.
objects
.
all
()
permission_classes
=
(
IsSuperUser
,)
...
...
@@ -69,14 +98,54 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
status
=
201
,
)
def
get_object
(
self
):
pk
=
self
.
kwargs
.
get
(
'pk'
)
or
self
.
request
.
query_params
.
get
(
'id'
)
if
not
pk
:
node
=
Node
.
root
()
else
:
node
=
get_object_or_404
(
Node
,
pk
=
pk
)
return
node
def
get_queryset
(
self
):
queryset
=
[]
query_all
=
self
.
request
.
query_params
.
get
(
"all"
)
query_assets
=
self
.
request
.
query_params
.
get
(
'assets'
)
node
=
self
.
get_object
()
if
node
==
Node
.
root
():
queryset
.
append
(
node
)
if
query_all
:
children
=
node
.
get_all_children
()
else
:
children
=
node
.
get_children
()
queryset
.
extend
(
list
(
children
))
if
query_assets
:
assets
=
node
.
get_assets
()
for
asset
in
assets
:
node_fake
=
Node
()
node_fake
.
id
=
asset
.
id
node_fake
.
parent
=
node
node_fake
.
value
=
asset
.
hostname
node_fake
.
is_asset
=
True
queryset
.
append
(
node_fake
)
return
queryset
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
instance
=
self
.
get_object
()
if
self
.
request
.
query_params
.
get
(
"all"
):
children
=
instance
.
get_all_children
()
return
super
()
.
list
(
request
,
*
args
,
**
kwargs
)
class
NodeAssetsApi
(
generics
.
ListAPIView
):
permission_classes
=
(
IsSuperUser
,)
serializer_class
=
serializers
.
AssetSerializer
def
get_queryset
(
self
):
node_id
=
self
.
kwargs
.
get
(
'pk'
)
query_all
=
self
.
request
.
query_params
.
get
(
'all'
)
instance
=
get_object_or_404
(
Node
,
pk
=
node_id
)
if
query_all
:
return
instance
.
get_all_assets
()
else
:
children
=
instance
.
get_children
()
response
=
[{
"id"
:
node
.
id
,
"key"
:
node
.
key
,
"value"
:
node
.
value
}
for
node
in
children
]
return
Response
(
response
,
status
=
200
)
return
instance
.
get_assets
()
class
NodeAddChildrenApi
(
generics
.
UpdateAPIView
):
...
...
@@ -146,4 +215,3 @@ class TestNodeConnectiveApi(APIView):
task_name
=
_
(
"测试节点下资产是否可连接: {}"
.
format
(
node
.
name
))
task
=
test_asset_connectability_util
.
delay
(
assets
,
task_name
=
task_name
)
return
Response
({
"task"
:
task
.
id
})
apps/assets/models/node.py
View file @
84634eb8
...
...
@@ -16,6 +16,8 @@ class Node(models.Model):
child_mark
=
models
.
IntegerField
(
default
=
0
)
date_create
=
models
.
DateTimeField
(
auto_now_add
=
True
)
is_asset
=
False
def
__str__
(
self
):
return
self
.
value
...
...
@@ -73,6 +75,9 @@ class Node(models.Model):
assets
=
Asset
.
objects
.
filter
(
nodes__in
=
nodes
)
return
assets
def
has_assets
(
self
):
return
self
.
get_all_assets
()
def
get_all_active_assets
(
self
):
return
self
.
get_all_assets
()
.
filter
(
is_active
=
True
)
...
...
apps/assets/models/user.py
View file @
84634eb8
...
...
@@ -123,8 +123,6 @@ class SystemUser(AssetUser):
def
get_assets
(
self
):
assets
=
set
(
self
.
assets
.
all
())
for
node
in
self
.
nodes
.
all
():
assets
.
update
(
set
(
node
.
get_all_assets
()))
return
assets
@property
...
...
apps/assets/serializers/node.py
View file @
84634eb8
...
...
@@ -42,7 +42,7 @@ class NodeSerializer(serializers.ModelSerializer):
class
Meta
:
model
=
Node
fields
=
[
'id'
,
'key'
,
'value'
,
'parent'
,
'assets_amount'
]
fields
=
[
'id'
,
'key'
,
'value'
,
'parent'
,
'assets_amount'
,
'is_asset'
]
list_serializer_class
=
BulkListSerializer
@staticmethod
...
...
apps/assets/tasks.py
View file @
84634eb8
...
...
@@ -276,7 +276,7 @@ def test_system_user_connectability_util(system_user, task_name):
:return:
"""
from
ops.utils
import
update_or_create_ansible_task
assets
=
system_user
.
assets
assets
=
system_user
.
get_assets
()
hosts
=
[
asset
.
hostname
for
asset
in
assets
if
asset
.
is_active
and
asset
.
is_unixlike
()]
tasks
=
const
.
TEST_SYSTEM_USER_CONN_TASKS
if
not
hosts
:
...
...
apps/assets/urls/api_urls.py
View file @
84634eb8
...
...
@@ -36,7 +36,9 @@ urlpatterns = [
url
(
r'^v1/system-user/(?P<pk>[0-9a-zA-Z\-]{36})/connective/$'
,
api
.
SystemUserTestConnectiveApi
.
as_view
(),
name
=
'system-user-connective'
),
url
(
r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/children/$'
,
api
.
NodeChildrenApi
.
as_view
(),
name
=
'node-children'
),
url
(
r'^v1/nodes/children/$'
,
api
.
NodeChildrenApi
.
as_view
(),
name
=
'node-children-2'
),
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/add/$'
,
api
.
NodeAddAssetsApi
.
as_view
(),
name
=
'node-add-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'
),
...
...
apps/common/fields.py
View file @
84634eb8
...
...
@@ -43,3 +43,7 @@ class StringIDField(serializers.Field):
def
to_representation
(
self
,
value
):
return
{
"pk"
:
value
.
pk
,
"name"
:
value
.
__str__
()}
class
StringManyToManyField
(
serializers
.
RelatedField
):
def
to_representation
(
self
,
value
):
return
value
.
__str__
()
\ No newline at end of file
apps/perms/api.py
View file @
84634eb8
...
...
@@ -6,6 +6,7 @@ from rest_framework.views import APIView, Response
from
rest_framework.generics
import
ListAPIView
,
get_object_or_404
from
rest_framework
import
viewsets
from
common.utils
import
set_or_append_attr_bulk
from
users.permissions
import
IsValidUser
,
IsSuperUser
,
IsSuperUserOrAppUser
from
.utils
import
AssetPermissionUtil
from
.models
import
AssetPermission
...
...
@@ -27,6 +28,31 @@ class AssetPermissionViewSet(viewsets.ModelViewSet):
return
serializers
.
AssetPermissionListSerializer
return
self
.
serializer_class
def
get_queryset
(
self
):
queryset
=
super
()
.
get_queryset
()
asset_id
=
self
.
request
.
query_params
.
get
(
'asset'
)
node_id
=
self
.
request
.
query_params
.
get
(
'node'
)
inherit_nodes
=
set
()
if
not
asset_id
and
not
node_id
:
return
queryset
permissions
=
set
()
if
asset_id
:
asset
=
get_object_or_404
(
Asset
,
pk
=
asset_id
)
permissions
=
set
(
queryset
.
filter
(
assets
=
asset
))
for
node
in
asset
.
nodes
.
all
():
inherit_nodes
.
update
(
set
(
node
.
ancestor_with_node
))
elif
node_id
:
node
=
get_object_or_404
(
Node
,
pk
=
node_id
)
permissions
=
set
(
queryset
.
filter
(
nodes
=
node
))
inherit_nodes
=
node
.
ancestor
for
n
in
inherit_nodes
:
_permissions
=
queryset
.
filter
(
nodes
=
n
)
set_or_append_attr_bulk
(
_permissions
,
"inherit"
,
n
.
value
)
permissions
.
update
(
_permissions
)
return
permissions
class
UserGrantedAssetsApi
(
ListAPIView
):
"""
...
...
apps/perms/forms.py
View file @
84634eb8
...
...
@@ -33,3 +33,22 @@ class AssetPermissionForm(forms.ModelForm):
labels
=
{
'nodes'
:
_
(
"Node"
),
}
def
clean_user_groups
(
self
):
users
=
self
.
cleaned_data
.
get
(
'users'
)
user_groups
=
self
.
cleaned_data
.
get
(
'user_groups'
)
if
not
users
and
not
user_groups
:
raise
forms
.
ValidationError
(
_
(
"User or group at least one required"
))
return
self
.
cleaned_data
[
"user_groups"
]
def
clean_asset_groups
(
self
):
assets
=
self
.
cleaned_data
.
get
(
'assets'
)
asset_groups
=
self
.
cleaned_data
.
get
(
'asset_groups'
)
if
not
assets
and
not
asset_groups
:
raise
forms
.
ValidationError
(
_
(
"Asset or group at least one required"
))
return
self
.
cleaned_data
[
"asset_groups"
]
apps/perms/models.py
View file @
84634eb8
...
...
@@ -31,7 +31,6 @@ class AssetPermission(models.Model):
objects
=
models
.
Manager
()
valid
=
ValidManager
()
inherit_from
=
None
def
__str__
(
self
):
return
self
.
name
...
...
@@ -46,78 +45,6 @@ class AssetPermission(models.Model):
return
True
return
False
def
get_granted_users
(
self
):
return
list
(
set
(
self
.
users
.
all
())
|
self
.
get_granted_user_groups_member
())
def
get_granted_user_groups_member
(
self
):
users
=
set
()
for
user_group
in
self
.
user_groups
.
all
():
for
user
in
user_group
.
users
.
all
():
setattr
(
user
,
'is_inherit_from_user_groups'
,
True
)
setattr
(
user
,
'inherit_from_user_groups'
,
getattr
(
user
,
'inherit_from_user_groups'
,
set
())
.
add
(
user_group
))
users
.
add
(
user
)
return
users
def
get_granted_assets
(
self
):
return
list
(
set
(
self
.
assets
.
all
())
|
self
.
get_granted_asset_groups_member
())
def
get_granted_asset_groups_member
(
self
):
assets
=
set
()
for
asset_group
in
self
.
asset_groups
.
all
():
for
asset
in
asset_group
.
assets
.
all
():
setattr
(
asset
,
'is_inherit_from_asset_groups'
,
True
)
setattr
(
asset
,
'inherit_from_asset_groups'
,
getattr
(
asset
,
'inherit_from_user_groups'
,
set
())
.
add
(
asset_group
))
assets
.
add
(
asset
)
return
assets
def
check_system_user_in_assets
(
self
):
errors
=
{}
assets
=
self
.
get_granted_assets
()
clusters
=
set
([
asset
.
cluster
for
asset
in
assets
])
for
system_user
in
self
.
system_users
.
all
():
cluster_remain
=
clusters
-
set
(
system_user
.
cluster
.
all
())
if
cluster_remain
:
errors
[
system_user
]
=
cluster_remain
return
errors
@property
def
users_detail
(
self
):
return
" "
.
join
([
u
.
name
for
u
in
self
.
users
.
all
()])
@property
def
user_groups_detail
(
self
):
return
" "
.
join
([
g
.
name
for
g
in
self
.
user_groups
.
all
()])
@property
def
assets_detail
(
self
):
return
" "
.
join
([
a
.
hostname
for
a
in
self
.
assets
.
all
()])
@property
def
nodes_detail
(
self
):
return
" "
.
join
([
g
.
value
for
g
in
self
.
nodes
.
all
()])
@property
def
system_users_detail
(
self
):
return
" "
.
join
([
s
.
name
for
s
in
self
.
system_users
.
all
()])
@property
def
detail
(
self
):
data
=
""
if
self
.
users
.
all
():
comment
=
_
(
"User"
)
users
=
"<b>{}: </b>"
.
format
(
comment
)
for
u
in
self
.
users
.
all
():
users
+=
u
.
name
+
" "
data
+=
users
+
"<br/>"
if
self
.
assets
.
all
():
assets
=
_
(
"<b>Assets: </b>"
)
for
a
in
self
.
assets
.
all
():
assets
+=
a
.
hostname
+
" "
data
+=
assets
+
"<br/>"
return
data
class
NodePermission
(
models
.
Model
):
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
...
...
apps/perms/serializers.py
View file @
84634eb8
...
...
@@ -3,19 +3,34 @@
from
rest_framework
import
serializers
from
.models
import
AssetPermission
from
common.fields
import
StringManyToManyField
class
AssetPermissionCreateUpdateSerializer
(
serializers
.
ModelSerializer
):
class
Meta
:
model
=
AssetPermission
exclude
=
(
'id'
,
'create_by'
,
'date_created'
)
exclude
=
(
'id'
,
'create
d
_by'
,
'date_created'
)
class
AssetPermissionListSerializer
(
serializers
.
ModelSerializer
):
users
=
StringManyToManyField
(
many
=
True
,
read_only
=
True
)
user_groups
=
StringManyToManyField
(
many
=
True
,
read_only
=
True
)
assets
=
StringManyToManyField
(
many
=
True
,
read_only
=
True
)
nodes
=
StringManyToManyField
(
many
=
True
,
read_only
=
True
)
system_users
=
StringManyToManyField
(
many
=
True
,
read_only
=
True
)
inherit
=
serializers
.
SerializerMethodField
()
class
Meta
:
model
=
AssetPermission
fields
=
'__all__'
@staticmethod
def
get_inherit
(
obj
):
if
hasattr
(
obj
,
'inherit'
):
return
obj
.
inherit
else
:
return
None
class
AssetPermissionUpdateUserSerializer
(
serializers
.
ModelSerializer
):
...
...
apps/perms/templates/perms/asset_permission_list.html
View file @
84634eb8
{% extends '_base_list.html' %}
{% load i18n %}
{% extends 'base.html' %}
{% load static %}
{% load common_tags %}
{% load i18n %}
{% 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>
<link
href=
"{% static 'css/plugins/jstree/style.min.css' %}"
rel=
"stylesheet"
>
<link
href=
"{% static 'css/plugins/ztree/awesomeStyle/awesome.css' %}"
rel=
"stylesheet"
>
<script
type=
"text/javascript"
src=
"{% static 'js/plugins/ztree/jquery.ztree.all.min.js' %}"
></script>
<style>
#search_btn
{
margin-bottom
:
0
;
.toggle
{
cursor
:
pointer
;
}
.detail-key
{
width
:
70px
;
}
</style>
{% endblock %}
{% block content_left_head %}
{% endblock %}
{% block table_search %}
<div
class=
"uc pull-left m-r-5"
>
<a
href=
"{% url 'perms:asset-permission-create' %}"
class=
"btn btn-sm btn-primary "
>
{% trans "Create permission" %}
</a>
</div>
<form
id=
"search_form"
method=
"get"
action=
""
class=
"pull-right form-inline"
style=
"padding-bottom: 8px"
>
<div
class=
"input-group"
>
<select
class=
"select2 form-control"
name=
"user"
>
<option
value=
""
>
{% trans 'User' %}
</option>
{% for u in user_list %}
<option
value=
"{{ u }}"
{%
if
u =
=
user
%}
selected
{%
endif
%}
>
{{ u }}
</option>
{% endfor %}
</select>
</div>
<div
class=
"input-group"
>
<select
class=
"select2 form-control"
name=
"user_group"
>
<option
value=
""
>
{% trans 'User group' %}
</option>
{% for g in user_group_list %}
<option
value=
"{{ g }}"
{%
if
g =
=
user_group
%}
selected
{%
endif
%}
>
{{ g }}
</option>
{% endfor %}
</select>
</div>
<div
class=
"input-group"
>
<select
class=
"select2 form-control"
name=
"asset"
>
<option
value=
""
>
{% trans 'Asset' %}
</option>
{% for a in asset_list %}
<option
value=
"{{ a }}"
{%
if
a =
=
asset
%}
selected
{%
endif
%}
>
{{ a }}
</option>
{% endfor %}
</select>
</div>
<div
class=
"input-group"
>
<select
class=
"select2 form-control"
name=
"node"
>
<option
value=
""
>
{% trans 'Node' %}
</option>
{% for n in node_list %}
<option
value=
"{{ n }}"
{%
if
n =
=
node
%}
selected
{%
endif
%}
>
{{ n }}
</option>
{% endfor %}
</select>
</div>
<div
class=
"input-group"
>
<select
class=
"select2 form-control"
name=
"system_user"
>
<option
value=
""
>
{% trans 'System user' %}
</option>
{% for s in system_user_list %}
<option
value=
"{{ s }}"
{%
if
s =
=
system_user
%}
selected
{%
endif
%}
>
{{ s }}
</option>
{% endfor %}
</select>
</div>
<div
class=
"input-group"
>
<input
type=
"text"
class=
"form-control input-sm"
name=
"q"
placeholder=
"{% trans 'Search' %}"
value=
"{{ q }}"
>
</div>
<div
class=
"input-group"
>
<div
class=
"input-group-btn"
>
<button
id=
'search_btn'
type=
"submit"
class=
"btn btn-sm btn-primary"
>
{% trans 'Search' %}
</button>
</div>
</div>
</form>
{% endblock %}
{% block table_container %}
<table
class=
"footable table table-stripped table-bordered toggle-arrow-tiny"
data-page=
"false"
>
<thead>
<tr>
<th
data-sorted=
"true"
data-toggle=
"true"
>
ID
</th>
<th>
{% trans 'Name' %}
</th>
<th
class=
"text-center"
>
{% trans 'User' %}
</th>
<th
class=
"text-center"
>
{% trans 'User group' %}
</th>
<th
class=
"text-center"
>
{% trans 'Asset' %}
</th>
<th
class=
"text-center"
>
{% trans 'Node'%}
</th>
<th
class=
"text-center"
>
{% trans 'System user' %}
</th>
<th
class=
"text-center"
>
{% trans 'Active' %}
</th>
<th
class=
"text-center"
>
{% trans 'Action' %}
</th>
<th
data-hide=
"all"
>
{% trans 'User' %}
</th>
<th
data-hide=
"all"
>
{% trans 'User group' %}
</th>
<th
data-hide=
"all"
>
{% trans 'Asset' %}
</th>
<th
data-hide=
"all"
>
{% trans 'Node' %}
</th>
<th
data-hide=
"all"
>
{% trans 'System user' %}
</th>
</tr>
</thead>
<tbody>
{% for object in object_list %}
<tr>
<td>
{{ forloop.counter }}
</td>
<td><a
href=
"#"
>
{{ object.name }}
</a></td>
<td
class=
"text-center"
>
{{ object.users.count }}
</td>
<td
class=
"text-center"
>
{{ object.user_groups.count }}
</td>
<td
class=
"text-center"
>
{{ object.assets.count }}
</td>
<td
class=
"text-center"
>
{{ object.nodes.count }}
</td>
<td
class=
"text-center"
>
{{ object.system_users.count }}
</td>
<td
class=
"text-center"
>
{% if object.is_valid %}
<i
class=
"fa fa-check text-navy"
></i>
{% else %}
<i
class=
"fa fa-times text-danger"
></i>
{% endif %}
</td>
<td
class=
"text-center"
>
<a
href=
"{% url 'perms:asset-permission-update' pk=object.id %}"
class=
"btn btn-xs btn-info"
>
{% trans "Update" %}
</a>
<a
data-uid=
"{{ object.id }}"
class=
"btn btn-xs btn-danger m-l-xs btn-delete"
>
{% trans "Delete" %}
</a>
</td>
<td>
{{ object.users_detail }}
</td>
<td>
{{ object.user_groups_detail }}
</td>
<td>
{{ object.assets_detail }}
</td>
<td>
{{ object.nodes_detail }}
</td>
<td>
{{ object.system_users_detail }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% block content %}
<div
class=
"wrapper wrapper-content"
>
<div
class=
"row"
>
<div
class=
"col-lg-3"
id=
"split-left"
style=
"padding-left: 3px"
>
<div
class=
"ibox float-e-margins"
>
<div
class=
"ibox-content mailbox-content"
style=
"padding-top: 0;padding-left: 1px"
>
<div
class=
"file-manager "
>
<div
id=
"assetTree"
class=
"ztree"
>
</div>
<div
class=
"clearfix"
></div>
</div>
</div>
</div>
</div>
<div
class=
"col-lg-9 animated fadeInRight"
id=
"split-right"
>
<div
class=
"tree-toggle"
>
<div
class=
"btn btn-sm btn-primary tree-toggle-btn"
onclick=
"toggle()"
>
<i
class=
"fa fa-angle-left fa-x"
id=
"toggle-icon"
></i>
</div>
</div>
<div
class=
"mail-box-header"
>
<div
class=
"uc pull-left m-r-5"
>
<a
class=
"btn btn-sm btn-primary btn-create-permission"
>
{% trans "Create permission" %}
</a>
</div>
<table
class=
"table table-striped table-bordered table-hover"
id=
"permission_list_table"
style=
"width: 100%"
>
<thead>
<tr>
<th></th>
<th>
{% trans 'Name' %}
</th>
<th
class=
"text-center"
>
{% trans 'User' %}
</th>
<th
class=
"text-center"
>
{% trans 'User group' %}
</th>
<th
class=
"text-center"
>
{% trans 'Asset' %}
</th>
<th
class=
"text-center"
>
{% trans 'Node'%}
</th>
<th
class=
"text-center"
>
{% trans 'System user' %}
</th>
<th
class=
"text-center"
>
{% trans 'Active' %}
</th>
<th
class=
"text-center"
>
{% trans 'Action' %}
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
</div>
{% 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>
$
(
document
).
ready
(
function
()
{
$
(
'.footable'
).
footable
();
$
(
'.select2'
).
select2
({
dropdownAutoWidth
:
true
,
width
:
'auto'
var
zTree
,
table
,
show
=
0
;
function
onSelected
(
event
,
treeNode
)
{
setCookie
(
'node_selected'
,
treeNode
.
id
);
var
url
=
table
.
ajax
.
url
();
if
(
treeNode
.
is_asset
)
{
url
=
setUrlParam
(
url
,
'node'
,
""
);
url
=
setUrlParam
(
url
,
'asset'
,
treeNode
.
id
)
}
else
{
url
=
setUrlParam
(
url
,
'asset'
,
""
);
url
=
setUrlParam
(
url
,
'node'
,
treeNode
.
id
)
}
setCookie
(
'node_selected'
,
treeNode
.
id
);
table
.
ajax
.
url
(
url
);
table
.
ajax
.
reload
();
}
function
selectQueryNode
()
{
var
query_node_id
=
$
.
getUrlParam
(
"node"
);
var
cookie_node_id
=
getCookie
(
'node_selected'
);
var
node
;
var
node_id
;
if
(
query_node_id
!==
null
)
{
node_id
=
query_node_id
}
else
if
(
cookie_node_id
!==
null
)
{
node_id
=
cookie_node_id
;
}
node
=
zTree
.
getNodesByParam
(
"id"
,
node_id
,
null
);
if
(
node
){
zTree
.
selectNode
(
node
[
0
]);
node
.
open
=
true
;
}
}
function
filter
(
treeId
,
parentNode
,
childNodes
)
{
$
.
each
(
childNodes
,
function
(
index
,
value
)
{
value
[
"pId"
]
=
value
[
"parent"
];
value
[
"name"
]
=
value
[
"value"
];
value
[
"isParent"
]
=
value
[
"assets_amount"
]
!==
0
;
value
[
"iconSkin"
]
=
value
[
"is_asset"
]
?
"file"
:
null
;
});
return
childNodes
;
}
function
beforeAsync
(
treeId
,
treeNode
)
{
return
true
;
}
function
makeLabel
(
data
)
{
return
"<label class='detail-key'><b>"
+
data
[
0
]
+
": </b></label>"
+
data
[
1
]
+
"</br>"
}
function
format
(
d
)
{
var
data
=
""
;
if
(
d
.
users
.
length
>
0
)
{
data
+=
makeLabel
([
"{% trans 'User' %}"
,
d
.
users
.
join
(
", "
)])
}
if
(
d
.
user_groups
.
length
>
0
)
{
data
+=
makeLabel
([
"{% trans 'User group' %}"
,
d
.
user_groups
.
join
(
", "
)])
}
if
(
d
.
assets
.
length
>
0
)
{
data
+=
makeLabel
([
"{% trans 'Asset' %}"
,
d
.
assets
.
join
(
", "
)])
}
if
(
d
.
nodes
.
length
>
0
)
{
data
+=
makeLabel
([
"{% trans 'Node' %}"
,
d
.
nodes
.
join
(
", "
)])
}
if
(
d
.
system_users
.
length
>
0
)
{
data
+=
makeLabel
([
"{% trans 'System user' %}"
,
d
.
system_users
.
join
(
", "
)])
}
return
data
}
function
initTable
()
{
var
options
=
{
ele
:
$
(
'#permission_list_table'
),
toggle
:
true
,
columnDefs
:
[
{
targets
:
0
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
$
(
td
).
addClass
(
"toggle"
);
$
(
td
).
html
(
"<i class='fa fa-angle-right'></i>"
);
}},
{
targets
:
1
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
detail_btn
=
'<a href="{% url "perms:asset-permission-detail" pk=DEFAULT_PK %}">'
+
cellData
+
'</a>'
;
$
(
td
).
html
(
detail_btn
.
replace
(
'{{ DEFAULT_PK }}'
,
rowData
.
id
));
}},
{
targets
:
2
,
createdCell
:
function
(
td
,
cellData
)
{
var
num
=
cellData
.
length
;
$
(
td
).
html
(
num
);
}},
{
targets
:
3
,
createdCell
:
function
(
td
,
cellData
)
{
var
num
=
cellData
.
length
;
$
(
td
).
html
(
num
);
}},
{
targets
:
4
,
createdCell
:
function
(
td
,
cellData
)
{
var
num
=
cellData
.
length
;
$
(
td
).
html
(
num
);
}},
{
targets
:
5
,
createdCell
:
function
(
td
,
cellData
)
{
var
num
=
cellData
.
length
;
$
(
td
).
html
(
num
);
}},
{
targets
:
6
,
createdCell
:
function
(
td
,
cellData
)
{
var
num
=
cellData
.
length
;
$
(
td
).
html
(
num
);
}},
{
targets
:
7
,
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
:
8
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
update_btn
=
'<a href="{% url "perms:asset-permission-update" pk=DEFAULT_PK %}" class="btn btn-xs m-l-xs btn-info">{% trans "Update" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
);
var
del_btn
=
'<a class="btn btn-xs btn-danger m-l-xs btn-del" data-uid="{{ DEFAULT_PK }}" mark=1 data-name="99991938">{% trans "Delete" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
)
.
replace
(
'99991938'
,
rowData
.
name
);
if
(
rowData
.
inherit
)
{
del_btn
=
del_btn
.
replace
(
"mark"
,
"disabled"
)
}
$
(
td
).
html
(
update_btn
+
del_btn
);
}}
],
ajax_url
:
'{% url "api-perms:asset-permission-list" %}'
,
columns
:
[
{
data
:
"id"
},
{
data
:
"name"
},
{
data
:
"users"
},
{
data
:
"user_groups"
},
{
data
:
"assets"
},
{
data
:
"nodes"
},
{
data
:
"system_users"
},
{
data
:
"is_active"
,
orderable
:
false
},
{
data
:
"id"
,
orderable
:
false
}
],
select
:
{},
op_html
:
$
(
'#actions'
).
html
()
};
table
=
jumpserver
.
initDataTable
(
options
);
return
table
}
function
initTree
()
{
var
setting
=
{
view
:
{
dblClickExpand
:
false
,
showLine
:
true
},
data
:
{
simpleData
:
{
enable
:
true
}
},
async
:
{
enable
:
true
,
url
:
"{% url 'api-assets:node-children-2' %}?assets=1"
,
autoParam
:[
"id"
,
"name=n"
,
"level=lv"
],
dataFilter
:
filter
,
type
:
'get'
},
callback
:
{
onSelected
:
onSelected
,
beforeAsync
:
beforeAsync
}
};
var
zNodes
=
[];
$
.
get
(
"{% url 'api-assets:node-children-2' %}"
,
function
(
data
,
status
){
$
.
each
(
data
,
function
(
index
,
value
)
{
value
[
"pId"
]
=
value
[
"parent"
];
value
[
"isParent"
]
=
value
[
"assets_amount"
]
!==
0
;
value
[
"name"
]
=
value
[
"value"
];
value
[
"open"
]
=
value
[
"key"
]
===
"0"
;
});
$
(
'#date .input-daterange'
).
datepicker
({
format
:
"yyyy-mm-dd"
,
todayBtn
:
"linked"
,
keyboardNavigation
:
false
,
forceParse
:
false
,
calendarWeeks
:
true
,
autoclose
:
true
zNodes
=
data
;
{
#
$
.
fn
.
zTree
.
init
(
$
(
"#assetTree"
),
setting
);
#
}
$
.
fn
.
zTree
.
init
(
$
(
"#assetTree"
),
setting
,
zNodes
);
zTree
=
$
.
fn
.
zTree
.
getZTreeObj
(
"assetTree"
);
selectQueryNode
();
});
}
function
toggle
()
{
if
(
show
===
0
)
{
$
(
"#split-left"
).
hide
(
500
,
function
()
{
$
(
"#split-right"
).
attr
(
"class"
,
"col-lg-12"
);
$
(
"#toggle-icon"
).
attr
(
"class"
,
"fa fa-angle-right fa-x"
);
show
=
1
;
});
}).
on
(
'click'
,
'.btn-delete'
,
function
()
{
var
$this
=
$
(
this
);
var
uid
=
$this
.
data
(
'uid'
);
var
the_url
=
'{% url "api-perms:asset-permission-detail" pk=DEFAULT_PK %}'
.
replace
(
'{{ DEFAULT_PK }}'
,
uid
);
var
name
=
$
(
this
).
closest
(
"tr"
).
find
(
":nth-child(2)"
).
children
(
'a'
).
html
();
objectDelete
(
$this
,
name
,
the_url
);
setTimeout
(
function
()
{
window
.
reload
();
},
1000
);
}
else
{
$
(
"#split-right"
).
attr
(
"class"
,
"col-lg-9"
);
$
(
"#toggle-icon"
).
attr
(
"class"
,
"fa fa-angle-left fa-x"
);
$
(
"#split-left"
).
show
(
500
);
show
=
0
;
}
}
$
(
document
).
ready
(
function
(){
initTable
();
initTree
();
})
.
on
(
'click'
,
'.btn-del'
,
function
()
{
var
$this
=
$
(
this
);
var
uid
=
$this
.
data
(
'uid'
);
var
name
=
$this
.
data
(
'name'
);
var
the_url
=
'{% url "api-perms:asset-permission-detail" pk=DEFAULT_PK %}'
.
replace
(
'{{ DEFAULT_PK }}'
,
uid
);
objectDelete
(
$this
,
name
,
the_url
);
})
.
on
(
'click'
,
'.btn-create-permission'
,
function
()
{
var
url
=
"{% url 'perms:asset-permission-create' %}"
;
var
nodes
=
zTree
.
getSelectedNodes
();
var
_nodes
=
[];
var
_assets
=
[];
$
.
each
(
nodes
,
function
(
id
,
node
)
{
if
(
node
.
is_asset
)
{
_assets
.
push
(
node
.
id
)
}
else
{
_nodes
.
push
(
node
.
id
)
}
});
</script>
{% endblock %}
url
+=
"?assets="
+
_assets
.
join
(
","
)
+
"&nodes="
+
_nodes
.
join
(
","
);
window
.
open
(
url
,
'_self'
);
}).
on
(
'click'
,
'.toggle'
,
function
(
e
)
{
e
.
preventDefault
();
var
detailRows
=
[];
var
tr
=
$
(
this
).
closest
(
'tr'
);
var
row
=
table
.
row
(
tr
);
var
idx
=
$
.
inArray
(
tr
.
attr
(
'id'
),
detailRows
);
if
(
row
.
child
.
isShown
())
{
tr
.
removeClass
(
'details'
);
row
.
child
.
hide
();
// Remove from the 'open' array
detailRows
.
splice
(
idx
,
1
);
}
else
{
tr
.
addClass
(
'details'
);
$
(
'.toggle i'
).
removeClass
(
'fa-angle-right'
).
addClass
(
'fa-angle-down'
);
row
.
child
(
format
(
row
.
data
())).
show
();
// Add to the 'open' array
if
(
idx
===
-
1
)
{
detailRows
.
push
(
tr
.
attr
(
'id'
));
}
}
})
</script>
{% endblock %}
apps/perms/urls/views_urls.py
View file @
84634eb8
...
...
@@ -9,7 +9,7 @@ urlpatterns = [
url
(
r'^asset-permission$'
,
views
.
AssetPermissionListView
.
as_view
(),
name
=
'asset-permission-list'
),
url
(
r'^asset-permission/create$'
,
views
.
AssetPermissionCreateView
.
as_view
(),
name
=
'asset-permission-create'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/update$'
,
views
.
AssetPermissionUpdateView
.
as_view
(),
name
=
'asset-permission-update'
),
#
url(r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})$', views.AssetPermissionDetailView.as_view(),name='asset-permission-detail'),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})$'
,
views
.
AssetPermissionDetailView
.
as_view
(),
name
=
'asset-permission-detail'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/delete$'
,
views
.
AssetPermissionDeleteView
.
as_view
(),
name
=
'asset-permission-delete'
),
# url(r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/user$', views.AssetPermissionUserView.as_view(), name='asset-permission-user-list'),
# url(r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/asset$', views.AssetPermissionAssetView.as_view(), name='asset-permission-asset-list'),
...
...
apps/perms/views.py
View file @
84634eb8
...
...
@@ -3,14 +3,14 @@
from
__future__
import
unicode_literals
,
absolute_import
from
django.utils.translation
import
ugettext
as
_
from
django.views.generic
import
ListView
,
CreateView
,
UpdateView
from
django.views.generic
import
ListView
,
CreateView
,
UpdateView
,
DetailView
from
django.views.generic.edit
import
DeleteView
from
django.urls
import
reverse_lazy
from
django.conf
import
settings
from
django.db.models
import
Q
from
.hands
import
AdminUserRequiredMixin
,
Node
,
User
,
UserGroup
,
Asset
,
SystemUser
from
.models
import
AssetPermission
,
NodePermission
from
common.utils
import
get_object_or_none
from
.hands
import
AdminUserRequiredMixin
,
Node
,
Asset
from
.models
import
AssetPermission
from
.forms
import
AssetPermissionForm
...
...
@@ -20,51 +20,9 @@ class AssetPermissionListView(AdminUserRequiredMixin, ListView):
paginate_by
=
settings
.
DISPLAY_PER_PAGE
user
=
user_group
=
asset
=
node
=
system_user
=
q
=
""
def
get_queryset
(
self
):
self
.
q
=
self
.
request
.
GET
.
get
(
'q'
,
''
)
self
.
user
=
self
.
request
.
GET
.
get
(
"user"
,
''
)
self
.
user_group
=
self
.
request
.
GET
.
get
(
"user_group"
,
''
)
self
.
asset
=
self
.
request
.
GET
.
get
(
'asset'
,
''
)
self
.
node
=
self
.
request
.
GET
.
get
(
'node'
,
''
)
self
.
system_user
=
self
.
request
.
GET
.
get
(
'system_user'
,
''
)
filter_kwargs
=
dict
()
if
self
.
user
:
filter_kwargs
[
'users__name'
]
=
self
.
user
if
self
.
user_group
:
filter_kwargs
[
'user_groups__name'
]
=
self
.
user_group
if
self
.
asset
:
filter_kwargs
[
'assets__hostname'
]
=
self
.
asset
if
self
.
node
:
filter_kwargs
[
'nodes__value'
]
=
self
.
node
if
self
.
system_user
:
filter_kwargs
[
'system_users__name'
]
=
self
.
system_user
queryset
=
self
.
model
.
objects
.
filter
(
**
filter_kwargs
)
if
self
.
q
:
queryset
=
queryset
.
filter
(
Q
(
name__contains
=
self
.
q
)
|
Q
(
users__name
=
self
.
q
)
|
Q
(
user_groups__name
=
self
.
q
)
|
Q
(
assets__hostname
=
self
.
q
)
|
Q
(
nodes__value
=
self
.
q
)
|
Q
(
system_users__name
=
self
.
q
)
)
queryset
=
queryset
.
order_by
(
'-date_start'
)
return
queryset
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
_
(
'Perms'
),
'user_list'
:
User
.
objects
.
all
()
.
values_list
(
'name'
,
flat
=
True
),
'user_group_list'
:
UserGroup
.
objects
.
all
()
.
values_list
(
'name'
,
flat
=
True
),
'asset_list'
:
Asset
.
objects
.
all
()
.
values_list
(
'hostname'
,
flat
=
True
),
'node_list'
:
Node
.
objects
.
all
()
.
values_list
(
'value'
,
flat
=
True
),
'system_user_list'
:
SystemUser
.
objects
.
all
()
.
values_list
(
'name'
,
flat
=
True
),
'user'
:
self
.
user
,
'user_group'
:
self
.
user_group
,
'asset'
:
self
.
asset
,
'node'
:
self
.
node
,
'system_user'
:
self
.
system_user
,
'q'
:
self
.
q
,
'action'
:
_
(
'Asset permission list'
),
}
kwargs
.
update
(
context
)
...
...
@@ -77,6 +35,19 @@ class AssetPermissionCreateView(AdminUserRequiredMixin, CreateView):
template_name
=
'perms/asset_permission_create_update.html'
success_url
=
reverse_lazy
(
'perms:asset-permission-list'
)
def
get_form
(
self
,
form_class
=
None
):
form
=
super
()
.
get_form
(
form_class
=
form_class
)
nodes_id
=
self
.
request
.
GET
.
get
(
"nodes"
)
.
split
(
","
)
assets_id
=
self
.
request
.
GET
.
get
(
"assets"
)
.
split
(
","
)
if
nodes_id
:
nodes
=
Node
.
objects
.
filter
(
id__in
=
nodes_id
)
form
[
'nodes'
]
.
initial
=
nodes
if
assets_id
:
assets
=
Asset
.
objects
.
filter
(
id__in
=
assets_id
)
form
[
'assets'
]
.
initial
=
assets
return
form
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
_
(
'Perms'
),
...
...
@@ -101,6 +72,21 @@ class AssetPermissionUpdateView(AdminUserRequiredMixin, UpdateView):
return
super
()
.
get_context_data
(
**
kwargs
)
class
AssetPermissionDetailView
(
AdminUserRequiredMixin
,
DetailView
):
model
=
AssetPermission
form_class
=
AssetPermissionForm
template_name
=
'perms/asset_permission_detail.html'
success_url
=
reverse_lazy
(
"perms:asset-permission-list"
)
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
_
(
'Perms'
),
'action'
:
_
(
'Update asset permission'
)
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
class
AssetPermissionDeleteView
(
AdminUserRequiredMixin
,
DeleteView
):
model
=
AssetPermission
template_name
=
'delete_confirm.html'
...
...
apps/static/css/plugins/ztree/awesomeStyle/awesome.css
View file @
84634eb8
...
...
@@ -212,49 +212,49 @@ website: http://code.google.com/p/jquerytree/
height
:
20px
;
}
.ztree
li
span
.button.root_open
::before
{
content
:
"\f
078
"
;
content
:
"\f
107
"
;
padding-top
:
10px
;
padding-left
:
2px
;
display
:
inline-block
;
}
.ztree
li
span
.button.root_close
::before
{
content
:
"\f
054
"
;
content
:
"\f
105
"
;
padding-top
:
10px
;
padding-left
:
2px
;
display
:
inline-block
;
}
.ztree
li
span
.button.roots_open
::before
{
content
:
"\f
078
"
;
content
:
"\f
107
"
;
padding-top
:
10px
;
padding-left
:
2px
;
display
:
inline-block
;
}
.ztree
li
span
.button.roots_close
::before
{
content
:
"\f
054
"
;
content
:
"\f
105
"
;
padding-top
:
10px
;
padding-left
:
2px
;
display
:
inline-block
;
}
.ztree
li
span
.button.center_open
::before
{
content
:
"\f
078
"
;
content
:
"\f
107
"
;
padding-top
:
10px
;
padding-left
:
2px
;
display
:
inline-block
;
}
.ztree
li
span
.button.center_close
::before
{
content
:
"\f
054
"
;
content
:
"\f
105
"
;
padding-top
:
10px
;
padding-left
:
2px
;
display
:
inline-block
;
}
.ztree
li
span
.button.bottom_open
::before
{
content
:
"\f
078
"
;
content
:
"\f
107
"
;
padding-top
:
10px
;
padding-left
:
2px
;
display
:
inline-block
;
}
.ztree
li
span
.button.bottom_close
::before
{
content
:
"\f
054
"
;
content
:
"\f
105
"
;
padding-top
:
10px
;
padding-left
:
2px
;
display
:
inline-block
;
...
...
@@ -300,7 +300,31 @@ website: http://code.google.com/p/jquerytree/
color
:
#676a6c
;
}
.ztree
li
span
.button.ico_docu
::before
{
content
:
"\f114"
;
content
:
"\f07b"
;
font-family
:
FontAwesome
;
padding-top
:
10px
;
padding-left
:
2px
;
display
:
inline-block
;
color
:
#676a6c
;
}
.ztree
li
span
.button.file_ico_docu
::before
{
content
:
"\f022"
;
font-family
:
FontAwesome
;
padding-top
:
10px
;
padding-left
:
2px
;
display
:
inline-block
;
color
:
#676a6c
;
}
.ztree
li
span
.button.linux_ico_docu
::before
{
content
:
"\f17c"
;
font-family
:
FontAwesome
;
padding-top
:
10px
;
padding-left
:
2px
;
display
:
inline-block
;
color
:
#676a6c
;
}
.ztree
li
span
.button.windows_ico_docu
::before
{
content
:
"\f17a"
;
font-family
:
FontAwesome
;
padding-top
:
10px
;
padding-left
:
2px
;
...
...
apps/static/css/plugins/ztree/awesomeStyle/awesome.less
View file @
84634eb8
...
...
@@ -39,11 +39,11 @@ website: http://code.google.com/p/jquerytree/
margin:0; padding:5px; color:@color-normal; background-color: @color-bg;
li {
padding:0; margin:0; list-style:none; line-height:17px; text-align:left; white-space:nowrap; outline:0;
ul {
ul {
margin: 0px; padding:0 0 0 18px;
}
ul.line { }
a {padding-right:3px; margin:0; cursor:pointer; height:@h; color:@color-normal; background-color: transparent;
a {padding-right:3px; margin:0; cursor:pointer; height:@h; color:@color-normal; background-color: transparent;
text-decoration:none; vertical-align:top; display: inline-block;
input.rename {height:14px; width:80px; padding:0; margin:0;
color: @color-bg; background-color: @color-normal;
...
...
@@ -64,11 +64,11 @@ website: http://code.google.com/p/jquerytree/
span.button {line-height:0; margin:0; padding: 0; width:@w; height:@h; display: inline-block; vertical-align:top;
border:0px solid; cursor: pointer;outline:none;
background-color:transparent; background-repeat:no-repeat; background-attachment: scroll;
&::before{color: @color-normal; font-family: FontAwesome; padding-top:@pad-top;}
&.chk { margin:0px; cursor: auto; width: 12px;
display: inline-block;padding-top:@pad-top;padding-left:@pad-left;
&.checkbox_false_full::before {content: @fa-square-o;}
&.checkbox_false_full_focus::before {content: @fa-square-o; color:@color-highlight;}
&.checkbox_false_part::before {content: @fa-square-o;color: @color-partial;}
...
...
@@ -82,7 +82,7 @@ website: http://code.google.com/p/jquerytree/
&.checkbox_true_part::before {content: @fa-check-square-o;color: @color-partial}
&.checkbox_true_part_focus::before {content: @fa-check-square-o;color: @color-partfocus;}
&.checkbox_true_disable::before {content: @fa-check-square-o;color: @color-disabled}
&.radio_false_full::before {content: @fa-circle-o;}
&.radio_false_full_focus::before {content: @fa-circle-o;color: @color-highlight}
&.radio_false_part::before {content: @fa-circle-o;color: @color-partial}
...
...
@@ -93,17 +93,17 @@ website: http://code.google.com/p/jquerytree/
&.radio_true_part::before {content: @fa-dot-circle-o;color: @color-partial}
&.radio_true_part_focus::before {content: @fa-dot-circle-o;color: @color-partial;}
&.radio_true_disable::before {content: @fa-circle-thin;color: @color-disabled}
}
&.switch {width:@w; height:@h}
&.root_open::before{content: @fa-
chevron
-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}
&.root_close::before{content: @fa-
chevron
-right;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}
&.roots_open::before{content: @fa-
chevron
-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}
&.roots_close::before{content: @fa-
chevron
-right;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}
&.center_open::before{content: @fa-
chevron
-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}
&.center_close::before{content: @fa-
chevron
-right;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}
&.bottom_open::before{content: @fa-
chevron
-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}
&.bottom_close::before{content: @fa-
chevron-right;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}
&.root_open::before{content: @fa-
angle
-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}
&.root_close::before{content: @fa-
angle
-right;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}
&.roots_open::before{content: @fa-
angle
-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}
&.roots_close::before{content: @fa-
angle
-right;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}
&.center_open::before{content: @fa-
angle
-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}
&.center_close::before{content: @fa-
angle
-right;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}
&.bottom_open::before{content: @fa-
angle
-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}
&.bottom_close::before{content: @fa-
angle-right;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}
&.noline_open{}
&.noline_close{}
&.root_docu{ background:none;}
...
...
@@ -111,11 +111,15 @@ website: http://code.google.com/p/jquerytree/
&.center_docu::before{padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}
&.bottom_docu::before{padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}
&.noline_docu{ background:none;}
&.ico_open::before {content: @fa-folder-open;font-family: FontAwesome;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}
&.ico_close::before {content: @fa-folder;font-family: FontAwesome;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}
&.ico_docu::before{content: @fa-folder-o;font-family: FontAwesome;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}
&.ico_docu::before{content: @fa-folder;font-family: FontAwesome;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}
&.file_ico_docu::before{content: @fa-list-alt;font-family: FontAwesome;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}
&.linux_ico_docu::before{content: @fa-linux;font-family: FontAwesome;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}
&.windows_ico_docu::before{content: @fa-windows;font-family: FontAwesome;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}
&.edit {margin-left:4px; margin-right: -1px; vertical-align:top; *vertical-align:middle;padding-top:@pad-top;}
&.edit::before{content: @fa-pencil-square-o;font-family: FontAwesome;}
...
...
apps/static/js/jumpserver.js
View file @
84634eb8
...
...
@@ -62,7 +62,6 @@ function GetTableDataBox() {
}
}
for
(
i
in
id_list
)
{
console
.
log
(
tabProduct
);
tableData
.
push
(
GetRowData
(
tabProduct
.
rows
[
id_list
[
i
]]));
}
...
...
@@ -240,6 +239,13 @@ $.fn.serializeObject = function()
});
return
o
;
};
function
makeLabel
(
data
)
{
return
"<label class='detail-key'><b>"
+
data
[
0
]
+
": </b></label>"
+
data
[
1
]
+
"</br>"
}
var
jumpserver
=
{};
jumpserver
.
checked
=
false
;
jumpserver
.
selected
=
{};
...
...
@@ -281,7 +287,7 @@ jumpserver.initDataTable = function (options) {
buttons
:
[],
columnDefs
:
columnDefs
,
ajax
:
{
url
:
options
.
ajax_url
,
url
:
options
.
ajax_url
,
dataSrc
:
""
},
columns
:
options
.
columns
||
[],
...
...
apps/users/views/login.py
View file @
84634eb8
...
...
@@ -2,7 +2,6 @@
from
__future__
import
unicode_literals
import
os
from
django
import
forms
from
django.shortcuts
import
render
from
django.contrib.auth
import
login
as
auth_login
,
logout
as
auth_logout
from
django.contrib.auth.mixins
import
LoginRequiredMixin
...
...
@@ -20,10 +19,9 @@ from django.views.generic.base import TemplateView
from
django.views.generic.edit
import
FormView
from
formtools.wizard.views
import
SessionWizardView
from
django.conf
import
settings
from
django.utils
import
timezone
from
common.utils
import
get_object_or_none
from
common.mixins
import
DatetimeSearchMixin
from
common.mixins
import
DatetimeSearchMixin
,
AdminUserRequiredMixin
from
..models
import
User
,
LoginLog
from
..utils
import
send_reset_password_mail
from
..tasks
import
write_login_log_async
...
...
@@ -228,7 +226,7 @@ class UserFirstLoginView(LoginRequiredMixin, SessionWizardView):
return
form
class
LoginLogListView
(
DatetimeSearchMixin
,
ListView
):
class
LoginLogListView
(
AdminUserRequiredMixin
,
DatetimeSearchMixin
,
ListView
):
template_name
=
'users/login_log_list.html'
model
=
LoginLog
paginate_by
=
settings
.
DISPLAY_PER_PAGE
...
...
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