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
21c71aba
Commit
21c71aba
authored
Oct 12, 2018
by
BaiJiangJie
Browse files
Options
Browse Files
Download
Plain Diff
[Update] Merge branch dev_cloud_manager (baijiangjie_local) to dev
parents
f8db9f48
7bafa546
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
42 changed files
with
919 additions
and
45 deletions
+919
-45
__init__.py
apps/__init__.py
+1
-1
__init__.py
apps/assets/api/__init__.py
+1
-0
cmd_filter.py
apps/assets/api/cmd_filter.py
+32
-0
system_user.py
apps/assets/api/system_user.py
+16
-3
__init__.py
apps/assets/forms/__init__.py
+1
-0
asset.py
apps/assets/forms/asset.py
+2
-2
cmd_filter.py
apps/assets/forms/cmd_filter.py
+27
-0
user.py
apps/assets/forms/user.py
+7
-3
__init__.py
apps/assets/models/__init__.py
+2
-1
asset.py
apps/assets/models/asset.py
+1
-1
cmd_filter.py
apps/assets/models/cmd_filter.py
+60
-0
node.py
apps/assets/models/node.py
+4
-6
user.py
apps/assets/models/user.py
+9
-1
__init__.py
apps/assets/serializers/__init__.py
+1
-0
cmd_filter.py
apps/assets/serializers/cmd_filter.py
+23
-0
_system_user.html
apps/assets/templates/assets/_system_user.html
+5
-0
admin_user_detail.html
apps/assets/templates/assets/admin_user_detail.html
+1
-1
cmd_filter_create_update.html
apps/assets/templates/assets/cmd_filter_create_update.html
+20
-0
cmd_filter_detail.html
apps/assets/templates/assets/cmd_filter_detail.html
+168
-0
cmd_filter_list.html
apps/assets/templates/assets/cmd_filter_list.html
+89
-0
cmd_filter_rule_create_update.html
...ssets/templates/assets/cmd_filter_rule_create_update.html
+75
-0
cmd_filter_rule_list.html
apps/assets/templates/assets/cmd_filter_rule_list.html
+115
-0
system_user_asset.html
apps/assets/templates/assets/system_user_asset.html
+2
-1
system_user_detail.html
apps/assets/templates/assets/system_user_detail.html
+0
-0
api_urls.py
apps/assets/urls/api_urls.py
+13
-2
views_urls.py
apps/assets/urls/views_urls.py
+8
-0
__init__.py
apps/assets/views/__init__.py
+1
-0
cmd_filter.py
apps/assets/views/cmd_filter.py
+169
-0
system_user.py
apps/assets/views/system_user.py
+4
-3
fields.py
apps/common/fields.py
+18
-0
common_tags.py
apps/common/templatetags/common_tags.py
+6
-0
django.mo
apps/locale/zh/LC_MESSAGES/django.mo
+0
-0
django.po
apps/locale/zh/LC_MESSAGES/django.po
+0
-0
views.py
apps/orgs/views.py
+2
-1
theme-gray.css
apps/static/plugins/elfinder/css/theme-gray.css
+7
-1
elfinder.zh_CN.js
apps/static/plugins/elfinder/i18n/elfinder.zh_CN.js
+1
-1
_footer.html
apps/templates/_footer.html
+1
-1
_nav.html
apps/templates/_nav.html
+6
-2
serializers.py
apps/terminal/serializers.py
+10
-13
views_urls.py
apps/terminal/urls/views_urls.py
+1
-0
terminal.py
apps/terminal/views/terminal.py
+9
-1
requirements.txt
requirements/requirements.txt
+1
-0
No files found.
apps/__init__.py
View file @
21c71aba
...
...
@@ -2,4 +2,4 @@
# -*- coding: utf-8 -*-
#
__version__
=
"1.4.
1
"
__version__
=
"1.4.
3
"
apps/assets/api/__init__.py
View file @
21c71aba
...
...
@@ -4,3 +4,4 @@ from .label import *
from
.system_user
import
*
from
.node
import
*
from
.domain
import
*
from
.cmd_filter
import
*
apps/assets/api/cmd_filter.py
0 → 100644
View file @
21c71aba
# -*- coding: utf-8 -*-
#
from
rest_framework_bulk
import
BulkModelViewSet
from
django.shortcuts
import
get_object_or_404
from
..hands
import
IsOrgAdmin
from
..models
import
CommandFilter
,
CommandFilterRule
from
..
import
serializers
__all__
=
[
'CommandFilterViewSet'
,
'CommandFilterRuleViewSet'
]
class
CommandFilterViewSet
(
BulkModelViewSet
):
permission_classes
=
(
IsOrgAdmin
,)
queryset
=
CommandFilter
.
objects
.
all
()
serializer_class
=
serializers
.
CommandFilterSerializer
class
CommandFilterRuleViewSet
(
BulkModelViewSet
):
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
serializers
.
CommandFilterRuleSerializer
def
get_queryset
(
self
):
fpk
=
self
.
kwargs
.
get
(
'filter_pk'
)
if
not
fpk
:
return
CommandFilterRule
.
objects
.
none
()
group
=
get_object_or_404
(
CommandFilter
,
pk
=
fpk
)
return
group
.
rules
.
all
()
.
order_by
(
'priority'
)
apps/assets/api/system_user.py
View file @
21c71aba
...
...
@@ -33,7 +33,8 @@ __all__ = [
'SystemUserViewSet'
,
'SystemUserAuthInfoApi'
,
'SystemUserPushApi'
,
'SystemUserTestConnectiveApi'
,
'SystemUserAssetsListView'
,
'SystemUserPushToAssetApi'
,
'SystemUserTestAssetConnectabilityApi'
,
'SystemUserTestAssetConnectabilityApi'
,
'SystemUserCommandFilterRuleListApi'
,
]
...
...
@@ -126,4 +127,17 @@ class SystemUserTestAssetConnectabilityApi(generics.RetrieveAPIView):
asset_id
=
self
.
kwargs
.
get
(
'aid'
)
asset
=
get_object_or_404
(
Asset
,
id
=
asset_id
)
task
=
test_system_user_connectability_a_asset
.
delay
(
system_user
,
asset
)
return
Response
({
"task"
:
task
.
id
})
\ No newline at end of file
return
Response
({
"task"
:
task
.
id
})
class
SystemUserCommandFilterRuleListApi
(
generics
.
ListAPIView
):
permission_classes
=
(
IsOrgAdminOrAppUser
,)
def
get_serializer_class
(
self
):
from
..serializers
import
CommandFilterRuleSerializer
return
CommandFilterRuleSerializer
def
get_queryset
(
self
):
pk
=
self
.
kwargs
.
get
(
'pk'
,
None
)
system_user
=
get_object_or_404
(
SystemUser
,
pk
=
pk
)
return
system_user
.
cmd_filter_rules
apps/assets/forms/__init__.py
View file @
21c71aba
...
...
@@ -4,3 +4,4 @@ from .asset import *
from
.label
import
*
from
.user
import
*
from
.domain
import
*
from
.cmd_filter
import
*
apps/assets/forms/asset.py
View file @
21c71aba
...
...
@@ -48,7 +48,7 @@ class AssetCreateForm(OrgModelForm):
'root or other NOPASSWD sudo privilege user existed in asset,'
'If asset is windows or other set any one, more see admin user left menu'
),
# 'platform': _("* required Must set exact system platform, Windows, Linux ...
"),
'platform'
:
_
(
"Windows 2016 RDP protocol is different, If is window 2016, set it
"
),
'domain'
:
_
(
"If your have some network not connect with each other, you can set domain"
)
}
...
...
@@ -88,7 +88,7 @@ class AssetUpdateForm(OrgModelForm):
'root or other NOPASSWD sudo privilege user existed in asset,'
'If asset is windows or other set any one, more see admin user left menu'
),
# 'platform': _("* required Must set exact system platform, Windows, Linux ...
"),
'platform'
:
_
(
"Windows 2016 RDP protocol is different, If is window 2016, set it
"
),
'domain'
:
_
(
"If your have some network not connect with each other, you can set domain"
)
}
...
...
apps/assets/forms/cmd_filter.py
0 → 100644
View file @
21c71aba
# -*- coding: utf-8 -*-
#
from
django
import
forms
from
orgs.mixins
import
OrgModelForm
from
..models
import
CommandFilter
,
CommandFilterRule
__all__
=
[
'CommandFilterForm'
,
'CommandFilterRuleForm'
]
class
CommandFilterForm
(
OrgModelForm
):
class
Meta
:
model
=
CommandFilter
fields
=
[
'name'
,
'comment'
]
class
CommandFilterRuleForm
(
OrgModelForm
):
class
Meta
:
model
=
CommandFilterRule
fields
=
[
'filter'
,
'type'
,
'content'
,
'priority'
,
'action'
,
'comment'
]
widgets
=
{
'content'
:
forms
.
Textarea
(
attrs
=
{
'placeholder'
:
'eg:
\r\n
reboot
\r\n
rm -rf'
}),
}
apps/assets/forms/user.py
View file @
21c71aba
...
...
@@ -3,8 +3,9 @@
from
django
import
forms
from
django.utils.translation
import
gettext_lazy
as
_
from
..models
import
AdminUser
,
SystemUser
from
common.utils
import
validate_ssh_private_key
,
ssh_pubkey_gen
,
get_logger
from
orgs.mixins
import
OrgModelForm
from
..models
import
AdminUser
,
SystemUser
logger
=
get_logger
(
__file__
)
__all__
=
[
...
...
@@ -85,7 +86,7 @@ class AdminUserForm(PasswordAndKeyAuthForm):
}
class
SystemUserForm
(
PasswordAndKeyAuthForm
):
class
SystemUserForm
(
OrgModelForm
,
PasswordAndKeyAuthForm
):
# Admin user assets define, let user select, save it in form not in view
auto_generate_key
=
forms
.
BooleanField
(
initial
=
True
,
required
=
False
)
...
...
@@ -136,11 +137,14 @@ class SystemUserForm(PasswordAndKeyAuthForm):
fields
=
[
'name'
,
'username'
,
'protocol'
,
'auto_generate_key'
,
'password'
,
'private_key_file'
,
'auto_push'
,
'sudo'
,
'comment'
,
'shell'
,
'priority'
,
'login_mode'
,
'comment'
,
'shell'
,
'priority'
,
'login_mode'
,
'cmd_filters'
,
]
widgets
=
{
'name'
:
forms
.
TextInput
(
attrs
=
{
'placeholder'
:
_
(
'Name'
)}),
'username'
:
forms
.
TextInput
(
attrs
=
{
'placeholder'
:
_
(
'Username'
)}),
'cmd_filters'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Command filter'
)
}),
}
help_texts
=
{
'name'
:
'* required'
,
...
...
apps/assets/models/__init__.py
View file @
21c71aba
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
from
.user
import
AdminUser
,
SystemUser
from
.user
import
*
from
.label
import
Label
from
.cluster
import
*
from
.group
import
*
from
.domain
import
*
from
.node
import
*
from
.asset
import
*
from
.cmd_filter
import
*
from
.utils
import
*
apps/assets/models/asset.py
View file @
21c71aba
...
...
@@ -15,7 +15,7 @@ from django.core.cache import cache
from
..const
import
ASSET_ADMIN_CONN_CACHE_KEY
from
.user
import
AdminUser
,
SystemUser
from
orgs.mixins
import
OrgModelMixin
,
OrgManager
from
orgs.mixins
import
OrgModelMixin
,
OrgManager
__all__
=
[
'Asset'
]
logger
=
logging
.
getLogger
(
__name__
)
...
...
apps/assets/models/cmd_filter.py
0 → 100644
View file @
21c71aba
# -*- coding: utf-8 -*-
#
import
uuid
from
django.db
import
models
from
django.core.validators
import
MinValueValidator
,
MaxValueValidator
from
django.utils.translation
import
ugettext_lazy
as
_
from
orgs.mixins
import
OrgModelMixin
__all__
=
[
'CommandFilter'
,
'CommandFilterRule'
]
class
CommandFilter
(
OrgModelMixin
):
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
name
=
models
.
CharField
(
max_length
=
64
,
verbose_name
=
_
(
"Name"
))
is_active
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
'Is active'
))
comment
=
models
.
TextField
(
blank
=
True
,
default
=
''
,
verbose_name
=
_
(
"Comment"
))
date_created
=
models
.
DateTimeField
(
auto_now_add
=
True
)
date_updated
=
models
.
DateTimeField
(
auto_now
=
True
)
created_by
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
default
=
''
,
verbose_name
=
_
(
'Created by'
))
def
__str__
(
self
):
return
self
.
name
class
CommandFilterRule
(
OrgModelMixin
):
TYPE_REGEX
=
'regex'
TYPE_COMMAND
=
'command'
TYPE_CHOICES
=
(
(
TYPE_REGEX
,
_
(
'Regex'
)),
(
TYPE_COMMAND
,
_
(
'Command'
)),
)
ACTION_DENY
,
ACTION_ALLOW
=
range
(
2
)
ACTION_CHOICES
=
(
(
ACTION_DENY
,
_
(
'Deny'
)),
(
ACTION_ALLOW
,
_
(
'Allow'
)),
)
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
filter
=
models
.
ForeignKey
(
'CommandFilter'
,
on_delete
=
models
.
CASCADE
,
verbose_name
=
_
(
"Filter"
),
related_name
=
'rules'
)
type
=
models
.
CharField
(
max_length
=
16
,
default
=
TYPE_COMMAND
,
choices
=
TYPE_CHOICES
,
verbose_name
=
_
(
"Type"
))
priority
=
models
.
IntegerField
(
default
=
50
,
verbose_name
=
_
(
"Priority"
),
help_text
=
_
(
"1-100, the lower will be match first"
),
validators
=
[
MinValueValidator
(
1
),
MaxValueValidator
(
100
)])
content
=
models
.
TextField
(
max_length
=
1024
,
verbose_name
=
_
(
"Content"
),
help_text
=
_
(
"One line one command"
))
action
=
models
.
IntegerField
(
default
=
ACTION_DENY
,
choices
=
ACTION_CHOICES
,
verbose_name
=
_
(
"Action"
))
comment
=
models
.
CharField
(
max_length
=
64
,
blank
=
True
,
default
=
''
,
verbose_name
=
_
(
"Comment"
))
date_created
=
models
.
DateTimeField
(
auto_now_add
=
True
)
date_updated
=
models
.
DateTimeField
(
auto_now
=
True
)
created_by
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
default
=
''
,
verbose_name
=
_
(
'Created by'
))
class
Meta
:
ordering
=
(
'priority'
,
'action'
)
def
__str__
(
self
):
return
'{}
%
{}'
.
format
(
self
.
type
,
self
.
content
)
apps/assets/models/node.py
View file @
21c71aba
...
...
@@ -40,12 +40,10 @@ class Node(OrgModelMixin):
return
True
self_key
=
[
int
(
k
)
for
k
in
self
.
key
.
split
(
':'
)]
other_key
=
[
int
(
k
)
for
k
in
other
.
key
.
split
(
':'
)]
if
len
(
self_key
)
<
len
(
other_key
):
return
True
elif
len
(
self_key
)
>
len
(
other_key
):
return
False
else
:
return
self_key
[
-
1
]
<
other_key
[
-
1
]
return
self_key
.
__lt__
(
other_key
)
def
__lt__
(
self
,
other
):
return
not
self
.
__gt__
(
other
)
@property
def
name
(
self
):
...
...
apps/assets/models/user.py
View file @
21c71aba
...
...
@@ -3,7 +3,6 @@
#
import
logging
import
uuid
from
django.core.cache
import
cache
from
django.db
import
models
...
...
@@ -118,6 +117,7 @@ class SystemUser(AssetUser):
sudo
=
models
.
TextField
(
default
=
'/bin/whoami'
,
verbose_name
=
_
(
'Sudo'
))
shell
=
models
.
CharField
(
max_length
=
64
,
default
=
'/bin/bash'
,
verbose_name
=
_
(
'Shell'
))
login_mode
=
models
.
CharField
(
choices
=
LOGIN_MODE_CHOICES
,
default
=
AUTO_LOGIN
,
max_length
=
10
,
verbose_name
=
_
(
'Login mode'
))
cmd_filters
=
models
.
ManyToManyField
(
'CommandFilter'
,
related_name
=
'system_users'
,
verbose_name
=
_
(
"Command filter"
),
blank
=
True
)
cache_key
=
"__SYSTEM_USER_CACHED_{}"
...
...
@@ -163,6 +163,14 @@ class SystemUser(AssetUser):
def
expire_cache
(
self
):
cache
.
delete
(
self
.
cache_key
.
format
(
self
.
id
))
@property
def
cmd_filter_rules
(
self
):
from
.cmd_filter
import
CommandFilterRule
rules
=
CommandFilterRule
.
objects
.
filter
(
filter__in
=
self
.
cmd_filters
.
all
()
)
.
order_by
(
'priority'
)
.
distinct
()
return
rules
@classmethod
def
get_system_user_by_id_or_cached
(
cls
,
sid
):
cached
=
cache
.
get
(
cls
.
cache_key
.
format
(
sid
))
...
...
apps/assets/serializers/__init__.py
View file @
21c71aba
...
...
@@ -7,3 +7,4 @@ from .label import *
from
.system_user
import
*
from
.node
import
*
from
.domain
import
*
from
.cmd_filter
import
*
apps/assets/serializers/cmd_filter.py
0 → 100644
View file @
21c71aba
# -*- coding: utf-8 -*-
#
from
rest_framework
import
serializers
from
common.fields
import
ChoiceDisplayField
from
..models
import
CommandFilter
,
CommandFilterRule
,
SystemUser
class
CommandFilterSerializer
(
serializers
.
ModelSerializer
):
rules
=
serializers
.
PrimaryKeyRelatedField
(
queryset
=
CommandFilterRule
.
objects
.
all
(),
many
=
True
)
system_users
=
serializers
.
PrimaryKeyRelatedField
(
queryset
=
SystemUser
.
objects
.
all
(),
many
=
True
)
class
Meta
:
model
=
CommandFilter
fields
=
'__all__'
class
CommandFilterRuleSerializer
(
serializers
.
ModelSerializer
):
serializer_choice_field
=
ChoiceDisplayField
class
Meta
:
model
=
CommandFilterRule
fields
=
'__all__'
apps/assets/templates/assets/_system_user.html
View file @
21c71aba
...
...
@@ -62,6 +62,10 @@
</div>
</div>
{% endblock %}
<div
id=
"command-filter-block"
>
<h3>
{% trans 'Command filter' %}
</h3>
{% bootstrap_field form.cmd_filters layout="horizontal" %}
</div>
<h3>
{% trans 'Other' %}
</h3>
{% bootstrap_field form.sudo layout="horizontal" %}
{% bootstrap_field form.shell layout="horizontal" %}
...
...
@@ -101,6 +105,7 @@ var need_change_field_login_mode = [
function
protocolChange
()
{
if
(
$
(
protocol_id
+
" option:selected"
).
text
()
===
'rdp'
)
{
$
(
'.auth-fields'
).
removeClass
(
'hidden'
);
$
(
'#command-filter-block'
).
addClass
(
'hidden'
);
$
.
each
(
need_change_field
,
function
(
index
,
value
)
{
$
(
value
).
closest
(
'.form-group'
).
addClass
(
'hidden'
)
});
...
...
apps/assets/templates/assets/admin_user_detail.html
View file @
21c71aba
...
...
@@ -90,7 +90,7 @@
<td
colspan=
"2"
class=
"no-borders"
>
<select
data-placeholder=
"{% trans 'Select nodes' %}"
id=
"nodes_selected"
class=
"select2"
style=
"width: 100%"
multiple=
""
tabindex=
"4"
>
{% for node in nodes %}
<option
value=
"{{ node.id }}"
id=
"opt_{{ node.id }}"
>
{{ node
.value
}}
</option>
<option
value=
"{{ node.id }}"
id=
"opt_{{ node.id }}"
>
{{ node }}
</option>
{% endfor %}
</select>
</td>
...
...
apps/assets/templates/assets/cmd_filter_create_update.html
0 → 100644
View file @
21c71aba
{% extends '_base_create_update.html' %}
{% load static %}
{% load bootstrap3 %}
{% load i18n %}
{% block form %}
<form
id=
"groupForm"
method=
"post"
class=
"form-horizontal"
>
{% csrf_token %}
{% bootstrap_field form.name layout="horizontal" %}
{% bootstrap_field form.comment layout="horizontal" %}
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
<button
class=
"btn btn-default"
type=
"reset"
>
{% trans 'Reset' %}
</button>
<button
id=
"submit_button"
class=
"btn btn-primary"
type=
"submit"
>
{% trans 'Submit' %}
</button>
</div>
</div>
</form>
{% endblock %}
apps/assets/templates/assets/cmd_filter_detail.html
0 → 100644
View file @
21c71aba
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
{% block custom_head_css_js %}
<link
href=
'{% static "css/plugins/select2/select2.min.css" %}'
rel=
"stylesheet"
>
<script
src=
'{% static "js/plugins/select2/select2.full.min.js" %}'
></script>
{% endblock %}
{% block content %}
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
<div
class=
"row"
>
<div
class=
"col-sm-12"
>
<div
class=
"ibox float-e-margins"
>
<div
class=
"panel-options"
>
<ul
class=
"nav nav-tabs"
>
<li
class=
"active"
>
<a
href=
"{% url 'assets:cmd-filter-detail' pk=object.id %}"
class=
"text-center"
>
<i
class=
"fa fa-laptop"
></i>
{% trans 'Detail' %}
</a>
</li>
<li>
<li>
<a
href=
"{% url 'assets:cmd-filter-rule-list' pk=object.id %}"
class=
"text-center"
>
<i
class=
"fa fa-laptop"
></i>
{% trans 'Rules' %}
</a>
</li>
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'assets:cmd-filter-update' pk=object.id %}"
><i
class=
"fa fa-edit"
></i>
{% trans 'Update' %}
</a>
</li>
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline btn-danger btn-del"
>
<i
class=
"fa fa-trash-o"
></i>
{% trans 'Delete' %}
</a>
</li>
</ul>
</div>
<div
class=
"tab-content"
>
<div
class=
"col-sm-8"
style=
"padding-left: 0;"
>
<div
class=
"ibox float-e-margins"
>
<div
class=
"ibox-title"
>
<span
class=
"label"
><b>
{{ object.name }}
</b></span>
<div
class=
"ibox-tools"
>
<a
class=
"collapse-link"
>
<i
class=
"fa fa-chevron-up"
></i>
</a>
<a
class=
"dropdown-toggle"
data-toggle=
"dropdown"
href=
"#"
>
<i
class=
"fa fa-wrench"
></i>
</a>
<ul
class=
"dropdown-menu dropdown-user"
>
</ul>
<a
class=
"close-link"
>
<i
class=
"fa fa-times"
></i>
</a>
</div>
</div>
<div
class=
"ibox-content"
>
<table
class=
"table"
>
<tbody>
<tr
class=
"no-borders-tr"
>
<td>
{% trans 'Name' %}:
</td>
<td><b>
{{ object.name }}
</b></td>
</tr>
<tr>
<td>
{% trans 'Comment' %}:
</td>
<td><b>
{{ object.comment }}
</b></td>
</tr>
<tr>
<td>
{% trans 'Date created' %}:
</td>
<td><b>
{{ object.date_created }}
</b></td>
</tr>
<tr>
<td>
{% trans 'Date updated' %}:
</td>
<td><b>
{{ object.date_updated }}
</b></td>
</tr>
<tr>
<td>
{% trans 'Created by' %}:
</td>
<td><b>
{{ object.created_by }}
</b></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div
class=
"col-sm-4"
style=
"padding-left: 0; padding-right: 0"
>
<div
class=
"panel panel-primary"
>
<div
class=
"panel-heading"
>
<i
class=
"fa fa-info-circle"
></i>
{% trans 'System users' %}
</div>
<div
class=
"panel-body"
>
<table
class=
"table group_edit"
id=
"table-clusters"
>
<tbody>
<form>
<tr>
<td
colspan=
"2"
class=
"no-borders"
>
<select
data-placeholder=
"{% trans 'Binding to system user' %}"
id=
"system_users_selected"
class=
"select2"
style=
"width: 100%"
multiple=
""
tabindex=
"4"
>
{% for system_user in system_users_remain %}
<option
value=
"{{ system_user.id }}"
id=
"opt_{{ system_user.id }}"
>
{{ system_user }}
</option>
{% endfor %}
</select>
</td>
</tr>
<tr>
<td
colspan=
"2"
class=
"no-borders"
>
<button
type=
"button"
class=
"btn btn-primary btn-sm"
id=
"btn-binding-system-users"
>
{% trans 'Confirm' %}
</button>
</td>
</tr>
</form>
{% for system_user in object.system_users.all %}
<tr>
<td><b
class=
"bdg-system-users"
data-gid=
{{
system_user
.
id
}}
>
{{ system_user }}
</b></td>
<td>
<button
class=
"btn btn-danger pull-right btn-xs btn-unbound-system-user"
data-gid=
{{
system_user
.
id
}}
type=
"button"
><i
class=
"fa fa-minus"
></i></button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script>
function
updateCMDFilterSystemUsers
(
system_users
)
{
var
the_url
=
"{% url 'api-assets:cmd-filter-detail' pk=object.id %}"
;
var
body
=
{
system_users
:
Object
.
assign
([],
system_users
)
};
var
success
=
function
(
data
)
{
location
.
reload
();
};
APIUpdateAttr
({
url
:
the_url
,
body
:
JSON
.
stringify
(
body
),
method
:
'PATCH'
,
success
:
success
});
}
$
(
document
).
ready
(
function
()
{
$
(
".select2"
).
select2
();
}).
on
(
'click'
,
'#btn-binding-system-users'
,
function
()
{
var
origin_system_users
=
$
.
map
(
$
(
".bdg-system-users"
),
function
(
s
)
{
return
$
(
s
).
data
(
'gid'
)
});
var
new_selected_system_users_id
=
$
.
map
(
$
(
"#system_users_selected"
).
select2
(
'data'
),
function
(
s
)
{
return
s
.
id
;
});
var
system_users
=
origin_system_users
.
concat
(
new_selected_system_users_id
);
updateCMDFilterSystemUsers
(
system_users
)
}).
on
(
'click'
,
'.btn-unbound-system-user'
,
function
()
{
var
unbound_system_user
=
$
(
this
).
data
(
'gid'
);
var
origin_system_users
=
$
.
map
(
$
(
".bdg-system-users"
),
function
(
s
)
{
return
$
(
s
).
data
(
'gid'
)
});
var
system_users
=
$
.
grep
(
origin_system_users
,
function
(
n
,
i
)
{
return
n
!==
unbound_system_user
});
updateCMDFilterSystemUsers
(
system_users
)
})
</script>
{% endblock %}
apps/assets/templates/assets/cmd_filter_list.html
0 → 100644
View file @
21c71aba
{% extends '_base_list.html' %}
{% load i18n static %}
{% block table_search %}{% endblock %}
{% block help_message %}
<div
class=
"alert alert-info help-message"
>
{% trans 'System user bound some command filter, each command filter has some rules,'%}
{% trans 'When user login asset with this system user, then run a command,' %}
{% trans 'The command will be filter by rules, higher priority(lower number) rule run first,' %}
{% trans 'When a rule matched, if rule action is allow, then allow command execute,' %}
{% trans 'else if action is deny, then command with be deny,' %}
{% trans 'else match next rule, if none matched, allowed' %}
</div>
{% endblock %}
{% block table_container %}
<div
class=
"uc pull-left m-r-5"
>
<a
href=
"{% url 'assets:cmd-filter-create' %}"
class=
"btn btn-sm btn-primary"
>
{% trans "Create command filter" %}
</a>
</div>
<table
class=
"table table-striped table-bordered table-hover "
id=
"cmd_filter_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 'Rules' %}
</th>
<th
class=
"text-center"
>
{% trans 'System users' %}
</th>
<th
class=
"text-center"
>
{% trans 'Comment' %}
</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
:
$
(
'#cmd_filter_list_table'
),
columnDefs
:
[
{
targets
:
1
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
detail_btn
=
'<a href="{% url '
assets
:
cmd
-
filter
-
detail
' pk=DEFAULT_PK %}">'
+
cellData
+
'</a>'
;
$
(
td
).
html
(
detail_btn
.
replace
(
'{{ DEFAULT_PK }}'
,
rowData
.
id
));
}},
{
targets
:
2
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
filters_list_btn
=
'<a href="{% url "assets:cmd-filter-rule-list" pk=DEFAULT_PK %}">'
+
cellData
.
length
+
'</a>'
;
filters_list_btn
=
filters_list_btn
.
replace
(
"{{ DEFAULT_PK }}"
,
rowData
.
id
);
$
(
td
).
html
(
filters_list_btn
);
}},
{
targets
:
3
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
system_users_list_btn
=
'<a href="{% url "assets:cmd-filter-detail" pk=DEFAULT_PK %}">'
+
cellData
.
length
+
'</a>'
;
system_users_list_btn
=
system_users_list_btn
.
replace
(
"{{ DEFAULT_PK }}"
,
rowData
.
id
);
$
(
td
).
html
(
system_users_list_btn
);
}},
{
targets
:
5
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
update_btn
=
'<a href="{% url "assets:cmd-filter-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
);
$
(
td
).
html
(
update_btn
+
del_btn
)
}}
],
ajax_url
:
'{% url "api-assets:cmd-filter-list" %}'
,
columns
:
[
{
data
:
"id"
},
{
data
:
"name"
},
{
data
:
"rules"
},
{
data
:
"system_users"
},
{
data
:
"comment"
},
{
data
:
"id"
}
],
op_html
:
$
(
'#actions'
).
html
()
};
jumpserver
.
initDataTable
(
options
);
}
$
(
document
).
ready
(
function
(){
initTable
();
})
.
on
(
'click'
,
'.btn-delete'
,
function
()
{
var
$this
=
$
(
this
);
var
$data_table
=
$
(
'#cmd_filter_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:cmd-filter-detail" pk=DEFAULT_PK %}'
.
replace
(
'{{ DEFAULT_PK }}'
,
uid
);
objectDelete
(
$this
,
name
,
the_url
);
setTimeout
(
function
()
{
$data_table
.
ajax
.
reload
();
},
3000
);
});
</script>
{% endblock %}
apps/assets/templates/assets/cmd_filter_rule_create_update.html
0 → 100644
View file @
21c71aba
{% extends 'base.html' %}
{% load i18n %}
{% load static %}
{% load bootstrap3 %}
{% block custom_head_css_js %}
<link
href=
"{% static 'css/plugins/select2/select2.min.css' %}"
rel=
"stylesheet"
>
<script
src=
"{% static 'js/plugins/select2/select2.full.min.js' %}"
></script>
{% endblock %}
{% block content %}
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
<div
class=
"row"
>
<div
class=
"col-sm-12"
>
<div
class=
"ibox float-e-margins"
>
<div
class=
"ibox-title"
>
<h5>
{{ action }}
</h5>
<div
class=
"ibox-tools"
>
<a
class=
"collapse-link"
>
<i
class=
"fa fa-chevron-up"
></i>
</a>
<a
class=
"dropdown-toggle"
data-toggle=
"dropdown"
href=
"#"
>
<i
class=
"fa fa-wrench"
></i>
</a>
<a
class=
"close-link"
>
<i
class=
"fa fa-times"
></i>
</a>
</div>
</div>
<div
class=
"ibox-content"
>
<form
enctype=
"multipart/form-data"
method=
"post"
class=
"form-horizontal"
action=
""
>
{% csrf_token %}
{% if form.non_field_errors %}
<div
class=
"alert alert-danger"
>
{{ form.non_field_errors }}
</div>
{% endif %}
{% bootstrap_form form layout="horizontal" %}
<div
class=
"form-group"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
<button
class=
"btn btn-white"
type=
"reset"
>
{% trans 'Reset' %}
</button>
<button
id=
"submit_button"
class=
"btn btn-primary"
type=
"submit"
>
{% trans 'Submit' %}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script>
var
content_origin_placeholder
=
''
;
var
content_origin_help_text
=
''
;
var
content_ref
=
''
;
var
content_help_ref
=
''
;
$
(
document
).
ready
(
function
(){
content_ref
=
$
(
'#id_content'
);
content_help_ref
=
content_ref
.
next
();
content_origin_placeholder
=
content_ref
.
attr
(
'placeholder'
);
content_origin_help_text
=
content_help_ref
.
html
();
}).
on
(
'change'
,
'#id_type'
,
function
()
{
if
(
$
(
'#id_type :selected'
).
val
()
===
'regex'
)
{
content_ref
.
attr
(
'placeholder'
,
'rm.*|reboot|shutdown'
);
content_help_ref
.
html
(
""
);
}
else
{
content_ref
.
attr
(
'placeholder'
,
content_origin_placeholder
);
content_help_ref
.
html
(
content_origin_help_text
);
}
})
</script>
{% endblock %}
\ No newline at end of file
apps/assets/templates/assets/cmd_filter_rule_list.html
0 → 100644
View file @
21c71aba
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
{% block custom_head_css_js %}
<link
href=
'{% static "css/plugins/select2/select2.min.css" %}'
rel=
"stylesheet"
>
<script
src=
'{% static "js/plugins/select2/select2.full.min.js" %}'
></script>
{% endblock %}
{% block content %}
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
<div
class=
"row"
>
<div
class=
"col-sm-12"
>
<div
class=
"ibox float-e-margins"
>
<div
class=
"panel-options"
>
<ul
class=
"nav nav-tabs"
>
<li>
<a
href=
"{% url 'assets:cmd-filter-detail' pk=object.id %}"
class=
"text-center"
>
<i
class=
"fa fa-laptop"
></i>
{% trans 'Detail' %}
</a>
</li>
<li
class=
"active"
>
<a
href=
"{% url 'assets:cmd-filter-rule-list' pk=object.id %}"
class=
"text-center"
><i
class=
"fa fa-laptop"
></i>
{% trans 'Rules' %}
</a>
</li>
</ul>
</div>
<div
class=
"tab-content"
>
<div
class=
"col-sm-12"
style=
"padding-left: 0;"
>
<div
class=
""
id=
"content_start"
>
</div>
<div
class=
"ibox float-e-margins"
>
<div
class=
"ibox-title"
>
<span
style=
"float: left"
><b>
{% trans 'Command filter rule list' %}
</b></span>
<div
class=
"ibox-tools"
>
<a
class=
"collapse-link"
>
<i
class=
"fa fa-chevron-up"
></i>
</a>
<a
class=
"dropdown-toggle"
data-toggle=
"dropdown"
href=
"#"
>
<i
class=
"fa fa-wrench"
></i>
</a>
<ul
class=
"dropdown-menu dropdown-user"
>
</ul>
<a
class=
"close-link"
>
<i
class=
"fa fa-times"
></i>
</a>
</div>
</div>
<div
class=
"ibox-content"
>
<div
class=
"uc pull-left m-r-5"
>
<a
href=
"{% url 'assets:cmd-filter-rule-create' filter_pk=object.id %}"
class=
"btn btn-sm btn-primary"
>
{% trans "Create rule" %}
</a>
</div>
<table
class=
"table table-striped table-bordered table-hover "
id=
"cmd_filter_rule_list_table"
>
<thead>
<tr>
<th
class=
"text-center"
>
<input
type=
"checkbox"
id=
"check_all"
class=
"ipt_check_all"
>
</th>
<th
class=
"text-center"
>
{% trans 'Type' %}
</th>
<th
class=
"text-center"
>
{% trans 'Content' %}
</th>
<th
class=
"text-center"
>
{% trans 'Priority' %}
</th>
<th
class=
"text-center"
>
{% trans 'Strategy' %}
</th>
<th
class=
"text-center"
>
{% trans 'Comment' %}
</th>
<th
class=
"text-center"
>
{% trans 'Action' %}
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block content_bottom_left %}{% endblock %}
{% block custom_foot_js %}
<script>
function
initTable
()
{
var
options
=
{
ele
:
$
(
'#cmd_filter_rule_list_table'
),
columnDefs
:
[
{
targets
:
6
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
update_btn
=
'<a href="{% url "assets:cmd-filter-rule-update" filter_pk=object.id 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
);
$
(
td
).
html
(
update_btn
+
del_btn
)
}}
],
ajax_url
:
'{% url "api-assets:cmd-filter-rule-list" filter_pk=object.id %}'
,
columns
:
[
{
data
:
"id"
},
{
data
:
"type.display"
},
{
data
:
'content'
},
{
data
:
'priority'
},
{
data
:
'action.display'
},
{
data
:
"comment"
},
{
data
:
"id"
}
],
op_html
:
$
(
'#actions'
).
html
()
};
jumpserver
.
initDataTable
(
options
);
}
$
(
document
).
ready
(
function
(){
initTable
();
})
.
on
(
'click'
,
'.btn-delete'
,
function
()
{
var
$this
=
$
(
this
);
var
$data_table
=
$
(
'#cmd_filter_rule_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:cmd-filter-rule-detail" filter_pk=object.id pk=DEFAULT_PK %}'
.
replace
(
'{{ DEFAULT_PK }}'
,
uid
);
objectDelete
(
$this
,
name
,
the_url
);
setTimeout
(
function
()
{
$data_table
.
ajax
.
reload
();
},
3000
);
})
</script>
{% endblock %}
apps/assets/templates/assets/system_user_asset.html
View file @
21c71aba
{% extends 'base.html' %}
{% load common_tags %}
{% load static %}
{% load i18n %}
...
...
@@ -113,7 +114,7 @@
</tr>
</form>
{% for node in system_user.nodes.all %}
{% for node in system_user.nodes.all
|sort
%}
<tr>
<td
><b
class=
"bdg_node"
data-gid=
{{
node
.
id
}}
>
{{ node }}
</b></td>
<td>
...
...
apps/assets/templates/assets/system_user_detail.html
View file @
21c71aba
This diff is collapsed.
Click to expand it.
apps/assets/urls/api_urls.py
View file @
21c71aba
# coding:utf-8
from
django.urls
import
path
from
..
import
api
from
rest_framework_nested
import
routers
# from rest_framework.routers import DefaultRouter
from
rest_framework_bulk.routes
import
BulkRouter
from
..
import
api
app_name
=
'assets'
router
=
BulkRouter
()
...
...
@@ -13,6 +16,11 @@ router.register(r'labels', api.LabelViewSet, 'label')
router
.
register
(
r'nodes'
,
api
.
NodeViewSet
,
'node'
)
router
.
register
(
r'domain'
,
api
.
DomainViewSet
,
'domain'
)
router
.
register
(
r'gateway'
,
api
.
GatewayViewSet
,
'gateway'
)
router
.
register
(
r'cmd-filter'
,
api
.
CommandFilterViewSet
,
'cmd-filter'
)
cmd_filter_router
=
routers
.
NestedDefaultRouter
(
router
,
r'cmd-filter'
,
lookup
=
'filter'
)
cmd_filter_router
.
register
(
r'rules'
,
api
.
CommandFilterRuleViewSet
,
'cmd-filter-rule'
)
urlpatterns
=
[
path
(
'assets-bulk/'
,
api
.
AssetListUpdateApi
.
as_view
(),
name
=
'asset-bulk-update'
),
...
...
@@ -42,6 +50,9 @@ urlpatterns = [
path
(
'system-user/<uuid:pk>/connective/'
,
api
.
SystemUserTestConnectiveApi
.
as_view
(),
name
=
'system-user-connective'
),
path
(
'system-user/<uuid:pk>/cmd-filter-rules/'
,
api
.
SystemUserCommandFilterRuleListApi
.
as_view
(),
name
=
'system-user-cmd-filter-rule-list'
),
path
(
'nodes/<uuid:pk>/children/'
,
api
.
NodeChildrenApi
.
as_view
(),
name
=
'node-children'
),
path
(
'nodes/children/'
,
api
.
NodeChildrenApi
.
as_view
(),
name
=
'node-children-2'
),
...
...
@@ -64,5 +75,5 @@ urlpatterns = [
api
.
GatewayTestConnectionApi
.
as_view
(),
name
=
'test-gateway-connective'
),
]
urlpatterns
+=
router
.
urls
urlpatterns
+=
router
.
urls
+
cmd_filter_router
.
urls
apps/assets/urls/views_urls.py
View file @
21c71aba
...
...
@@ -49,4 +49,12 @@ urlpatterns = [
path
(
'domain/<uuid:pk>/gateway/create/'
,
views
.
DomainGatewayCreateView
.
as_view
(),
name
=
'domain-gateway-create'
),
path
(
'domain/gateway/<uuid:pk>/update/'
,
views
.
DomainGatewayUpdateView
.
as_view
(),
name
=
'domain-gateway-update'
),
path
(
'cmd-filter/'
,
views
.
CommandFilterListView
.
as_view
(),
name
=
'cmd-filter-list'
),
path
(
'cmd-filter/create/'
,
views
.
CommandFilterCreateView
.
as_view
(),
name
=
'cmd-filter-create'
),
path
(
'cmd-filter/<uuid:pk>/update/'
,
views
.
CommandFilterUpdateView
.
as_view
(),
name
=
'cmd-filter-update'
),
path
(
'cmd-filter/<uuid:pk>/'
,
views
.
CommandFilterDetailView
.
as_view
(),
name
=
'cmd-filter-detail'
),
path
(
'cmd-filter/<uuid:pk>/rule/'
,
views
.
CommandFilterRuleListView
.
as_view
(),
name
=
'cmd-filter-rule-list'
),
path
(
'cmd-filter/<uuid:filter_pk>/rule/create/'
,
views
.
CommandFilterRuleCreateView
.
as_view
(),
name
=
'cmd-filter-rule-create'
),
path
(
'cmd-filter/<uuid:filter_pk>/rule/<uuid:pk>/update/'
,
views
.
CommandFilterRuleUpdateView
.
as_view
(),
name
=
'cmd-filter-rule-update'
),
]
apps/assets/views/__init__.py
View file @
21c71aba
...
...
@@ -4,3 +4,4 @@ from .system_user import *
from
.admin_user
import
*
from
.label
import
*
from
.domain
import
*
from
.cmd_filter
import
*
apps/assets/views/cmd_filter.py
0 → 100644
View file @
21c71aba
# -*- coding: utf-8 -*-
#
from
django.views.generic
import
TemplateView
,
CreateView
,
\
UpdateView
,
DeleteView
,
DetailView
from
django.views.generic.detail
import
SingleObjectMixin
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.urls
import
reverse_lazy
from
django.shortcuts
import
get_object_or_404
,
reverse
from
common.permissions
import
AdminUserRequiredMixin
from
common.const
import
create_success_msg
,
update_success_msg
from
..models
import
CommandFilter
,
CommandFilterRule
,
SystemUser
from
..forms
import
CommandFilterForm
,
CommandFilterRuleForm
__all__
=
(
"CommandFilterListView"
,
"CommandFilterCreateView"
,
"CommandFilterUpdateView"
,
"CommandFilterRuleListView"
,
"CommandFilterRuleCreateView"
,
"CommandFilterRuleUpdateView"
,
"CommandFilterDetailView"
,
)
class
CommandFilterListView
(
AdminUserRequiredMixin
,
TemplateView
):
template_name
=
'assets/cmd_filter_list.html'
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
_
(
'Assets'
),
'action'
:
_
(
'Command filter list'
),
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
class
CommandFilterCreateView
(
AdminUserRequiredMixin
,
CreateView
):
model
=
CommandFilter
template_name
=
'assets/cmd_filter_create_update.html'
form_class
=
CommandFilterForm
success_url
=
reverse_lazy
(
'assets:cmd-filter-list'
)
success_message
=
create_success_msg
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
_
(
'Assets'
),
'action'
:
_
(
'Create command filter'
),
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
class
CommandFilterUpdateView
(
AdminUserRequiredMixin
,
UpdateView
):
model
=
CommandFilter
template_name
=
'assets/cmd_filter_create_update.html'
form_class
=
CommandFilterForm
success_url
=
reverse_lazy
(
'assets:cmd-filter-list'
)
success_message
=
update_success_msg
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
_
(
'Assets'
),
'action'
:
_
(
'Update command filter'
),
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
class
CommandFilterDetailView
(
AdminUserRequiredMixin
,
DetailView
):
model
=
CommandFilter
template_name
=
'assets/cmd_filter_detail.html'
def
get_context_data
(
self
,
**
kwargs
):
system_users_remain
=
SystemUser
.
objects
\
.
exclude
(
cmd_filters
=
self
.
object
)
\
.
exclude
(
protocol
=
'rdp'
)
context
=
{
'app'
:
_
(
'Assets'
),
'action'
:
_
(
'Command filter detail'
),
'system_users_remain'
:
system_users_remain
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
class
CommandFilterRuleListView
(
AdminUserRequiredMixin
,
SingleObjectMixin
,
TemplateView
):
template_name
=
'assets/cmd_filter_rule_list.html'
model
=
CommandFilter
object
=
None
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
self
.
object
=
self
.
get_object
(
queryset
=
self
.
model
.
objects
.
all
())
return
super
()
.
get
(
request
,
*
args
,
**
kwargs
)
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
_
(
'Assets'
),
'action'
:
_
(
'Command filter rule list'
),
'object'
:
self
.
get_object
()
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
class
CommandFilterRuleCreateView
(
AdminUserRequiredMixin
,
CreateView
):
template_name
=
'assets/cmd_filter_rule_create_update.html'
model
=
CommandFilterRule
form_class
=
CommandFilterRuleForm
success_message
=
create_success_msg
cmd_filter
=
None
def
get_success_url
(
self
):
return
reverse
(
'assets:cmd-filter-rule-list'
,
kwargs
=
{
'pk'
:
self
.
cmd_filter
.
id
})
def
get_form
(
self
,
form_class
=
None
):
form
=
super
()
.
get_form
(
form_class
=
form_class
)
form
[
'filter'
]
.
initial
=
self
.
cmd_filter
form
[
'filter'
]
.
field
.
widget
.
attrs
[
'readonly'
]
=
1
return
form
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
filter_pk
=
self
.
kwargs
.
get
(
'filter_pk'
)
self
.
cmd_filter
=
get_object_or_404
(
CommandFilter
,
pk
=
filter_pk
)
return
super
()
.
dispatch
(
request
,
*
args
,
**
kwargs
)
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
_
(
'Assets'
),
'action'
:
_
(
'Create command filter rule'
),
'object'
:
self
.
cmd_filter
,
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
class
CommandFilterRuleUpdateView
(
AdminUserRequiredMixin
,
UpdateView
):
template_name
=
'assets/cmd_filter_rule_create_update.html'
model
=
CommandFilterRule
form_class
=
CommandFilterRuleForm
success_message
=
create_success_msg
cmd_filter
=
None
def
get_success_url
(
self
):
return
reverse
(
'assets:cmd-filter-rule-list'
,
kwargs
=
{
'pk'
:
self
.
cmd_filter
.
id
})
def
get_form
(
self
,
form_class
=
None
):
form
=
super
()
.
get_form
(
form_class
=
form_class
)
form
[
'filter'
]
.
initial
=
self
.
cmd_filter
form
[
'filter'
]
.
field
.
widget
.
attrs
[
'readonly'
]
=
1
return
form
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
filter_pk
=
self
.
kwargs
.
get
(
'filter_pk'
)
self
.
cmd_filter
=
get_object_or_404
(
CommandFilter
,
pk
=
filter_pk
)
return
super
()
.
dispatch
(
request
,
*
args
,
**
kwargs
)
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
_
(
'Assets'
),
'action'
:
_
(
'Update command filter rule'
),
'object'
:
self
.
cmd_filter
,
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
\ No newline at end of file
apps/assets/views/system_user.py
View file @
21c71aba
...
...
@@ -9,7 +9,7 @@ from django.views.generic.detail import DetailView
from
common.const
import
create_success_msg
,
update_success_msg
from
..forms
import
SystemUserForm
from
..models
import
SystemUser
,
Node
from
..models
import
SystemUser
,
Node
,
CommandFilter
from
common.permissions
import
AdminUserRequiredMixin
...
...
@@ -73,7 +73,7 @@ class SystemUserDetailView(AdminUserRequiredMixin, DetailView):
context
=
{
'app'
:
_
(
'Assets'
),
'action'
:
_
(
'System user detail'
),
'
nodes_remain'
:
Node
.
objects
.
exclude
(
systemuser
=
self
.
object
)
'
cmd_filters_remain'
:
CommandFilter
.
objects
.
exclude
(
system_users
=
self
.
object
)
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
...
...
@@ -91,10 +91,11 @@ class SystemUserAssetView(AdminUserRequiredMixin, DetailView):
context_object_name
=
'system_user'
def
get_context_data
(
self
,
**
kwargs
):
nodes_remain
=
sorted
(
Node
.
objects
.
exclude
(
systemuser
=
self
.
object
),
reverse
=
True
)
context
=
{
'app'
:
_
(
'assets'
),
'action'
:
_
(
'System user asset'
),
'nodes_remain'
:
Node
.
objects
.
exclude
(
systemuser
=
self
.
object
)
'nodes_remain'
:
nodes_remain
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
apps/common/fields.py
View file @
21c71aba
...
...
@@ -86,3 +86,21 @@ class FormEncryptCharField(FormEncryptMixin, forms.CharField):
class
FormEncryptDictField
(
FormEncryptMixin
,
FormDictField
):
pass
class
ChoiceDisplayField
(
serializers
.
ChoiceField
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
ChoiceDisplayField
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
choice_strings_to_display
=
{
six
.
text_type
(
key
):
value
for
key
,
value
in
self
.
choices
.
items
()
}
def
to_representation
(
self
,
value
):
if
value
is
None
:
return
value
return
{
'value'
:
self
.
choice_strings_to_values
.
get
(
six
.
text_type
(
value
),
value
),
'display'
:
self
.
choice_strings_to_display
.
get
(
six
.
text_type
(
value
),
value
),
}
apps/common/templatetags/common_tags.py
View file @
21c71aba
...
...
@@ -100,3 +100,9 @@ def is_bool_field(field):
@register.filter
def
to_dict
(
data
):
return
dict
(
data
)
@register.filter
def
sort
(
data
):
print
(
data
)
return
sorted
(
data
)
apps/locale/zh/LC_MESSAGES/django.mo
View file @
21c71aba
No preview for this file type
apps/locale/zh/LC_MESSAGES/django.po
View file @
21c71aba
This diff is collapsed.
Click to expand it.
apps/orgs/views.py
View file @
21c71aba
...
...
@@ -14,7 +14,8 @@ class SwitchOrgView(DetailView):
pk
=
kwargs
.
get
(
'pk'
)
self
.
object
=
Organization
.
get_instance
(
pk
)
request
.
session
[
'oid'
]
=
self
.
object
.
id
.
__str__
()
return
redirect
(
'index'
)
referer
=
request
.
META
.
get
(
'HTTP_REFERER'
,
reverse
(
'index'
))
return
redirect
(
referer
)
class
SwitchToAOrgView
(
View
):
...
...
apps/static/plugins/elfinder/css/theme-gray.css
View file @
21c71aba
...
...
@@ -1528,9 +1528,15 @@ a.ui-button:active .ui-icon,
.std42-dialog
.ui-dialog-titlebar
.elfinder-titlebar-minimize
:hover
.ui-icon
{
background-color
:
#ff9800
;
}
.elfinder-dialog-title
{
.elfinder-dialog-title
{
color
:
#f1f1f1
;
}
.ui-dialog-buttonpane
{
background
:
#fff
;
}
.std42-dialog
.ui-dialog-content
{
background
:
#fff
;
}
...
...
apps/static/plugins/elfinder/i18n/elfinder.zh_CN.js
View file @
21c71aba
...
...
@@ -375,7 +375,7 @@
'pass'
:
'密码'
,
// added 18.04.2012
'confirmUnmount'
:
'确实要卸载 $1?'
,
// from v2.1 added 30.04.2012
'dropFilesBrowser'
:
'从浏览器中拖放或粘贴文件'
,
// from v2.1 added 30.05.2012
'dropPasteFiles'
:
'拖放文件,
粘贴网址或
剪贴板图像'
,
// from v2.1 added 07.04.2014
'dropPasteFiles'
:
'拖放文件,
或粘贴
剪贴板图像'
,
// from v2.1 added 07.04.2014
'encoding'
:
'编码'
,
// from v2.1 added 19.12.2014
'locale'
:
'语言环境'
,
// from v2.1 added 19.12.2014
'searchTarget'
:
'目标: $1'
,
// from v2.1 added 22.5.2015
...
...
apps/templates/_footer.html
View file @
21c71aba
{% load i18n %}
<div
class=
"footer fixed"
>
<div
class=
"pull-right"
>
Version
<strong>
1.4.
1
-{% include '_build.html' %}
</strong>
GPLv2.
Version
<strong>
1.4.
3
-{% include '_build.html' %}
</strong>
GPLv2.
<!--<img style="display: none" src="http://www.jumpserver.org/img/evaluate_avatar1.jpg">-->
</div>
<div>
...
...
apps/templates/_nav.html
View file @
21c71aba
...
...
@@ -24,6 +24,7 @@
<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=
"label"
><a
href=
"{% url 'assets:label-list' %}"
>
{% trans 'Labels' %}
</a></li>
<li
id=
"cmd-filter"
><a
href=
"{% url 'assets:cmd-filter-list' %}"
>
{% trans 'Command filters' %}
</a></li>
</ul>
</li>
<li
id=
"perms"
>
...
...
@@ -47,6 +48,11 @@
<span
class=
"nav-label"
>
{% trans 'Web terminal' %}
</span>
</a>
</li>
<li>
<a
href=
"{% url 'terminal:web-sftp' %}"
target=
"_blank"
>
<span
class=
"nav-label"
>
{% trans 'File manager' %}
</span>
</a>
</li>
{% if request.user.is_superuser %}
<li
id=
"terminal"
><a
href=
"{% url 'terminal:terminal-list' %}"
>
{% trans 'Terminal' %}
</a></li>
{% endif %}
...
...
@@ -91,10 +97,8 @@
{% for plugin in XPACK_PLUGINS %}
<li
id=
"{{ plugin.name }}"
><a
href=
"{{ plugin.endpoint }}"
>
{% trans plugin.verbose_name %}
</a></li>
{% endfor %}
<li
id=
"id_cloud_account"
><a
href=
"{% url 'xpack:cloud:account-list' %}"
>
{% trans 'Account list' %}
</a></li>
<li
id=
"id_cloud_sync_task"
><a
href=
"{% url 'xpack:cloud:sync-task-list' %}"
>
{% trans 'Sync task list' %}
</a></li>
</ul>
</li>
{% endif %}
...
...
apps/terminal/serializers.py
View file @
21c71aba
# -*- coding: utf-8 -*-
#
from
django.core.cache
import
cache
from
django.utils
import
timezone
from
rest_framework
import
serializers
from
rest_framework_bulk.serializers
import
BulkListSerializer
...
...
@@ -28,19 +29,8 @@ class TerminalSerializer(serializers.ModelSerializer):
@staticmethod
def
get_is_alive
(
obj
):
try
:
status
=
obj
.
status_set
.
latest
()
except
Status
.
DoesNotExist
:
status
=
None
if
not
status
:
return
False
delta
=
timezone
.
now
()
-
status
.
date_created
if
delta
<
timezone
.
timedelta
(
seconds
=
600
):
return
True
else
:
return
False
key
=
StatusSerializer
.
CACHE_KEY_PREFIX
+
str
(
obj
.
id
)
return
cache
.
get
(
key
)
class
SessionSerializer
(
BulkSerializerMixin
,
serializers
.
ModelSerializer
):
...
...
@@ -57,11 +47,18 @@ class SessionSerializer(BulkSerializerMixin, serializers.ModelSerializer):
class
StatusSerializer
(
serializers
.
ModelSerializer
):
CACHE_KEY_PREFIX
=
'terminal_status_'
class
Meta
:
fields
=
'__all__'
model
=
Status
def
create
(
self
,
validated_data
):
terminal_id
=
str
(
validated_data
[
'terminal'
]
.
id
)
key
=
self
.
CACHE_KEY_PREFIX
+
terminal_id
cache
.
set
(
key
,
1
,
60
)
return
validated_data
class
TaskSerializer
(
BulkSerializerMixin
,
serializers
.
ModelSerializer
):
...
...
apps/terminal/urls/views_urls.py
View file @
21c71aba
...
...
@@ -16,6 +16,7 @@ urlpatterns = [
path
(
'terminal/<uuid:pk>/update/'
,
views
.
TerminalUpdateView
.
as_view
(),
name
=
'terminal-update'
),
path
(
'<uuid:pk>/accept/'
,
views
.
TerminalAcceptView
.
as_view
(),
name
=
'terminal-accept'
),
path
(
'web-terminal/'
,
views
.
WebTerminalView
.
as_view
(),
name
=
'web-terminal'
),
path
(
'web-sftp/'
,
views
.
WebSFTPView
.
as_view
(),
name
=
'web-sftp'
),
# Session view
path
(
'session-online/'
,
views
.
SessionOnlineListView
.
as_view
(),
name
=
'session-online-list'
),
...
...
apps/terminal/views/terminal.py
View file @
21c71aba
...
...
@@ -16,7 +16,7 @@ from common.permissions import SuperUserRequiredMixin
__all__
=
[
"TerminalListView"
,
"TerminalUpdateView"
,
"TerminalDetailView"
,
"TerminalDeleteView"
,
"TerminalConnectView"
,
"TerminalAcceptView"
,
"WebTerminalView"
,
"WebTerminalView"
,
'WebSFTPView'
,
]
...
...
@@ -93,6 +93,9 @@ class TerminalAcceptView(SuperUserRequiredMixin, JSONResponseMixin, UpdateView):
class
TerminalConnectView
(
LoginRequiredMixin
,
SuperUserRequiredMixin
,
DetailView
):
"""
Abandon
"""
template_name
=
'flash_message_standalone.html'
model
=
Terminal
...
...
@@ -121,3 +124,8 @@ class TerminalConnectView(LoginRequiredMixin, SuperUserRequiredMixin, DetailView
class
WebTerminalView
(
LoginRequiredMixin
,
View
):
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
return
redirect
(
'/luna/?'
+
request
.
GET
.
urlencode
())
class
WebSFTPView
(
LoginRequiredMixin
,
View
):
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
return
redirect
(
'/coco/elfinder/sftp/?'
+
request
.
GET
.
urlencode
())
requirements/requirements.txt
View file @
21c71aba
...
...
@@ -71,3 +71,4 @@ urllib3==1.22
vine==1.1.4
drf-yasg==1.9.1
Werkzeug==0.14.1
drf-nested-routers==0.90.2
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