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
5bbad019
Commit
5bbad019
authored
Jan 16, 2018
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Feature] 增加标签
parent
dad21cad
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
212 additions
and
4 deletions
+212
-4
api.py
apps/assets/api.py
+17
-3
__init__.py
apps/assets/models/__init__.py
+1
-0
asset.py
apps/assets/models/asset.py
+2
-0
label.py
apps/assets/models/label.py
+30
-0
user.py
apps/assets/models/user.py
+1
-0
serializers.py
apps/assets/serializers.py
+42
-1
label_list.html
apps/assets/templates/assets/label_list.html
+72
-0
api_urls.py
apps/assets/urls/api_urls.py
+1
-0
views_urls.py
apps/assets/urls/views_urls.py
+1
-0
__init__.py
apps/assets/views/__init__.py
+1
-0
label.py
apps/assets/views/label.py
+43
-0
_nav.html
apps/templates/_nav.html
+1
-0
No files found.
apps/assets/api.py
View file @
5bbad019
...
...
@@ -17,15 +17,15 @@ from rest_framework import generics
from
rest_framework.response
import
Response
from
rest_framework_bulk
import
BulkModelViewSet
from
rest_framework_bulk
import
ListBulkCreateUpdateDestroyAPIView
from
django.shortcuts
import
get_object_or_404
from
django.db.models
import
Q
from
rest_framework.pagination
import
LimitOffsetPagination
from
django.shortcuts
import
get_object_or_404
from
django.db.models
import
Q
,
Count
from
common.mixins
import
CustomFilterMixin
from
common.utils
import
get_logger
from
.hands
import
IsSuperUser
,
IsValidUser
,
IsSuperUserOrAppUser
,
\
get_user_granted_assets
from
.models
import
AssetGroup
,
Asset
,
Cluster
,
SystemUser
,
AdminUser
from
.models
import
AssetGroup
,
Asset
,
Cluster
,
SystemUser
,
AdminUser
,
Label
from
.
import
serializers
from
.tasks
import
update_asset_hardware_info_manual
,
test_admin_user_connectability_manual
,
\
test_asset_connectability_manual
,
push_system_user_to_cluster_assets_manual
,
\
...
...
@@ -295,3 +295,17 @@ class SystemUserTestConnectiveApi(generics.RetrieveAPIView):
system_user
=
self
.
get_object
()
test_system_user_connectability_manual
.
delay
(
system_user
)
return
Response
({
"msg"
:
"Task created"
})
class
LabelViewSet
(
BulkModelViewSet
):
queryset
=
Label
.
objects
.
annotate
(
asset_count
=
Count
(
"assets"
))
\
.
annotate
(
admin_user_count
=
Count
(
"adminuser"
))
\
.
annotate
(
system_user_count
=
Count
(
"systemuser"
))
permission_classes
=
(
IsSuperUser
,)
serializer_class
=
serializers
.
LabelSerializer
def
list
(
self
,
request
,
*
args
,
**
kwargs
):
if
request
.
query_params
.
get
(
"distinct"
):
self
.
serializer_class
=
serializers
.
LabelDistinctSerializer
self
.
queryset
=
self
.
queryset
.
values
(
"name"
)
.
distinct
()
return
super
()
.
list
(
request
,
*
args
,
**
kwargs
)
apps/assets/models/__init__.py
View file @
5bbad019
...
...
@@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
#
from
.user
import
AdminUser
,
SystemUser
from
.label
import
Label
from
.cluster
import
*
from
.group
import
*
from
.asset
import
*
...
...
apps/assets/models/asset.py
View file @
5bbad019
...
...
@@ -88,6 +88,8 @@ class Asset(models.Model):
os_arch
=
models
.
CharField
(
max_length
=
16
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'OS arch'
))
hostname_raw
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Hostname raw'
))
labels
=
models
.
ManyToManyField
(
'assets.Label'
,
blank
=
True
,
related_name
=
'assets'
,
verbose_name
=
_
(
"Labels"
))
created_by
=
models
.
CharField
(
max_length
=
32
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Created by'
))
date_created
=
models
.
DateTimeField
(
auto_now_add
=
True
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Date created'
))
comment
=
models
.
TextField
(
max_length
=
128
,
default
=
''
,
blank
=
True
,
verbose_name
=
_
(
'Comment'
))
...
...
apps/assets/models/label.py
0 → 100644
View file @
5bbad019
# -*- coding: utf-8 -*-
#
import
uuid
from
django.db
import
models
from
django.utils.translation
import
ugettext_lazy
as
_
class
Label
(
models
.
Model
):
SYSTEM_CATEGORY
=
"S"
USER_CATEGORY
=
"U"
CATEGORY_CHOICES
=
(
(
"S"
,
_
(
"System"
)),
(
"U"
,
_
(
"User"
))
)
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
name
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
"Name"
))
value
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
"Value"
))
category
=
models
.
CharField
(
max_length
=
128
,
choices
=
CATEGORY_CHOICES
,
verbose_name
=
_
(
"Category"
))
is_active
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
"Is active"
))
comment
=
models
.
TextField
(
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
"Comment"
))
date_created
=
models
.
DateTimeField
(
auto_now_add
=
True
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Date created'
)
)
def
__str__
(
self
):
return
"{}:{}"
.
format
(
self
.
name
,
self
.
value
)
class
Meta
:
db_table
=
"assets_label"
apps/assets/models/user.py
View file @
5bbad019
...
...
@@ -30,6 +30,7 @@ class AssetUser(models.Model):
_password
=
models
.
CharField
(
max_length
=
256
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Password'
))
_private_key
=
models
.
TextField
(
max_length
=
4096
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'SSH private key'
),
validators
=
[
private_key_validator
,
])
_public_key
=
models
.
TextField
(
max_length
=
4096
,
blank
=
True
,
verbose_name
=
_
(
'SSH public key'
))
labels
=
models
.
ManyToManyField
(
'assets.Label'
,
blank
=
True
,
verbose_name
=
_
(
"Labels"
))
comment
=
models
.
TextField
(
blank
=
True
,
verbose_name
=
_
(
'Comment'
))
date_created
=
models
.
DateTimeField
(
auto_now_add
=
True
)
date_updated
=
models
.
DateTimeField
(
auto_now
=
True
)
...
...
apps/assets/serializers.py
View file @
5bbad019
...
...
@@ -4,7 +4,7 @@ from rest_framework import serializers
from
rest_framework_bulk.serializers
import
BulkListSerializer
from
common.mixins
import
BulkSerializerMixin
from
.models
import
AssetGroup
,
Asset
,
Cluster
,
AdminUser
,
SystemUser
from
.models
import
AssetGroup
,
Asset
,
Cluster
,
AdminUser
,
SystemUser
,
Label
from
.const
import
ADMIN_USER_CONN_CACHE_KEY
,
SYSTEM_USER_CONN_CACHE_KEY
...
...
@@ -284,3 +284,44 @@ class MyAssetGroupGrantedSerializer(serializers.ModelSerializer):
@staticmethod
def
get_assets_amount
(
obj
):
return
len
(
obj
.
assets_granted
)
class
LabelSerializer
(
serializers
.
ModelSerializer
):
asset_count
=
serializers
.
SerializerMethodField
()
admin_user_count
=
serializers
.
SerializerMethodField
()
system_user_count
=
serializers
.
SerializerMethodField
()
class
Meta
:
model
=
Label
fields
=
'__all__'
list_serializer_class
=
BulkListSerializer
@staticmethod
def
get_asset_count
(
obj
):
return
obj
.
asset_count
@staticmethod
def
get_admin_user_count
(
obj
):
return
obj
.
admin_user_count
@staticmethod
def
get_system_user_count
(
obj
):
return
obj
.
system_user_count
def
get_field_names
(
self
,
declared_fields
,
info
):
fields
=
super
()
.
get_field_names
(
declared_fields
,
info
)
fields
.
extend
([
'get_category_display'
])
return
fields
class
LabelDistinctSerializer
(
serializers
.
ModelSerializer
):
value
=
serializers
.
SerializerMethodField
()
class
Meta
:
model
=
Label
fields
=
(
"name"
,
"value"
)
@staticmethod
def
get_value
(
obj
):
labels
=
Label
.
objects
.
filter
(
name
=
obj
[
"name"
])
return
', '
.
join
([
label
.
value
for
label
in
labels
])
apps/assets/templates/assets/label_list.html
0 → 100644
View file @
5bbad019
{% extends '_base_list.html' %}
{% load i18n static %}
{% block table_search %}{% endblock %}
{% block table_container %}
<div
class=
"uc pull-left m-r-5"
>
<a
href=
""
class=
"btn btn-sm btn-primary"
>
{% trans "Create label" %}
</a>
</div>
<table
class=
"table table-striped table-bordered table-hover "
id=
"label_list_table"
>
<thead>
<tr>
<th
class=
"text-center"
>
<input
type=
"checkbox"
id=
"check_all"
class=
"ipt_check_all"
>
</th>
<th
class=
"text-center"
>
{% trans 'Name' %}
</th>
<th
class=
"text-center"
>
{% trans 'Value' %}
</th>
<th
class=
"text-center"
>
{% trans 'Asset' %}
</th>
<th
class=
"text-center"
>
{% trans 'Admin user' %}
</th>
<th
class=
"text-center"
>
{% trans 'System user' %}
</th>
<th
class=
"text-center"
>
{% trans 'Action' %}
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
{% endblock %}
{% block content_bottom_left %}{% endblock %}
{% block custom_foot_js %}
<script>
function
initTable
()
{
var
options
=
{
ele
:
$
(
'#label_list_table'
),
columnDefs
:
[
{
targets
:
1
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
{
#
var
detail_btn
=
'<a href="{% url "assets:label-detail" pk=DEFAULT_PK %}">'
+
cellData
+
'</a>'
;
#
}
var
detail_btn
=
'<a>'
+
cellData
+
'</a>'
;
$
(
td
).
html
(
detail_btn
.
replace
(
'{{ DEFAULT_PK }}'
,
rowData
.
id
));
}},
{
targets
:
6
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
update_btn
=
'<a href="{% url "assets:cluster-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_cluster_delete" data-uid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
);
$
(
td
).
html
(
update_btn
+
del_btn
)
}}],
ajax_url
:
'{% url "api-assets:label-list" %}?sort=name'
,
columns
:
[
{
data
:
"id"
},
{
data
:
"name"
},
{
data
:
"value"
},
{
data
:
"asset_count"
},
{
data
:
"admin_user_count"
},
{
data
:
"system_user_count"
},
{
data
:
"id"
}
],
op_html
:
$
(
'#actions'
).
html
()
};
jumpserver
.
initDataTable
(
options
);
}
$
(
document
).
ready
(
function
(){
initTable
();
})
.
on
(
'click'
,
'.btn_cluster_delete'
,
function
()
{
var
$this
=
$
(
this
);
var
$data_table
=
$
(
'#cluster_list_table'
).
DataTable
();
var
name
=
$
(
this
).
closest
(
"tr"
).
find
(
":nth-child(2)"
).
children
(
'a'
).
html
();
var
uid
=
$this
.
data
(
'uid'
);
var
the_url
=
'{% url "api-assets:cluster-detail" pk=DEFAULT_PK %}'
.
replace
(
'{{ DEFAULT_PK }}'
,
uid
);
objectDelete
(
$this
,
name
,
the_url
);
setTimeout
(
function
()
{
$data_table
.
ajax
.
reload
();
},
3000
);
});
</script>
{% endblock %}
apps/assets/urls/api_urls.py
View file @
5bbad019
...
...
@@ -12,6 +12,7 @@ router.register(r'v1/assets', api.AssetViewSet, 'asset')
router
.
register
(
r'v1/clusters'
,
api
.
ClusterViewSet
,
'cluster'
)
router
.
register
(
r'v1/admin-user'
,
api
.
AdminUserViewSet
,
'admin-user'
)
router
.
register
(
r'v1/system-user'
,
api
.
SystemUserViewSet
,
'system-user'
)
router
.
register
(
r'v1/labels'
,
api
.
LabelViewSet
,
'label'
)
urlpatterns
=
[
url
(
r'^v1/assets-bulk/$'
,
api
.
AssetListUpdateApi
.
as_view
(),
name
=
'asset-bulk-update'
),
...
...
apps/assets/urls/views_urls.py
View file @
5bbad019
...
...
@@ -53,5 +53,6 @@ urlpatterns = [
# url(r'^system-user/(?P<pk>[0-9a-zA-Z\-]{36})/asset-group$', views.SystemUserAssetGroupView.as_view(),
# name='system-user-asset-group'),
url
(
r'^label/$'
,
views
.
LabelListView
.
as_view
(),
name
=
'label-list'
),
]
apps/assets/views/__init__.py
View file @
5bbad019
...
...
@@ -4,4 +4,5 @@ from .group import *
from
.cluster
import
*
from
.system_user
import
*
from
.admin_user
import
*
from
.label
import
*
apps/assets/views/label.py
0 → 100644
View file @
5bbad019
# -*- coding: utf-8 -*-
#
from
django.views.generic
import
ListView
,
TemplateView
,
CreateView
,
\
UpdateView
,
DeleteView
,
DetailView
from
django.utils.translation
import
ugettext_lazy
as
_
from
common.mixins
import
AdminUserRequiredMixin
__all__
=
(
"LabelListView"
,
"LabelCreateView"
,
"LabelUpdateView"
,
"LabelDetailView"
,
"LabelDeleteView"
,
)
class
LabelListView
(
AdminUserRequiredMixin
,
TemplateView
):
template_name
=
'assets/label_list.html'
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
_
(
'Assets'
),
'action'
:
_
(
'Label list'
),
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
class
LabelCreateView
(
AdminUserRequiredMixin
,
CreateView
):
pass
class
LabelUpdateView
(
AdminUserRequiredMixin
,
UpdateView
):
pass
class
LabelDetailView
(
AdminUserRequiredMixin
,
DetailView
):
pass
class
LabelDeleteView
(
AdminUserRequiredMixin
,
DeleteView
):
pass
apps/templates/_nav.html
View file @
5bbad019
...
...
@@ -24,6 +24,7 @@
<li
id=
"cluster"
><a
href=
"{% url 'assets:cluster-list' %}"
>
{% trans 'Cluster' %}
</a></li>
<li
id=
"admin-user"
><a
href=
"{% url 'assets:admin-user-list' %}"
>
{% trans 'Admin user' %}
</a></li>
<li
id=
"system-user"
><a
href=
"{% url 'assets:system-user-list' %}"
>
{% trans 'System user' %}
</a></li>
<li
id=
"system-user"
><a
href=
"{% url 'assets:label-list' %}"
>
{% trans 'Label' %}
</a></li>
</ul>
</li>
<li
id=
"perms"
>
...
...
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