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
7f3d32a8
Commit
7f3d32a8
authored
7 years ago
by
q4speed
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/dev' into dev
parents
6d7b5968
b2b123b4
master
auditor_jym
audits
dev
dev_beta
dev_beta_db
gengmei
node_service
password
rbac
restrict_access
test
v52
wph
1.5.2
1.5.1
1.5.0
1.4.10
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.3
1.3.2
1.3.1
1.3.0
1.2.1
1.2.0
1.1.1
1.1.0
1.0.0
v1.4.10
v1.4.7
v1.4.4
No related merge requests found
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
84 changed files
with
628 additions
and
589 deletions
+628
-589
api.py
apps/assets/api.py
+25
-19
forms.py
apps/assets/forms.py
+58
-25
asset.py
apps/assets/models/asset.py
+12
-1
cluster.py
apps/assets/models/cluster.py
+1
-0
group.py
apps/assets/models/group.py
+1
-0
user.py
apps/assets/models/user.py
+8
-3
serializers.py
apps/assets/serializers.py
+11
-2
signals_handler.py
apps/assets/signals_handler.py
+9
-8
tasks.py
apps/assets/tasks.py
+21
-8
_system_user.html
apps/assets/templates/assets/_system_user.html
+2
-2
admin_user_assets.html
apps/assets/templates/assets/admin_user_assets.html
+4
-4
admin_user_create_update.html
apps/assets/templates/assets/admin_user_create_update.html
+2
-2
admin_user_detail.html
apps/assets/templates/assets/admin_user_detail.html
+2
-3
admin_user_list.html
apps/assets/templates/assets/admin_user_list.html
+40
-5
asset_detail.html
apps/assets/templates/assets/asset_detail.html
+2
-2
asset_group_create.html
apps/assets/templates/assets/asset_group_create.html
+18
-107
asset_group_detail.html
apps/assets/templates/assets/asset_group_detail.html
+15
-5
asset_group_list.html
apps/assets/templates/assets/asset_group_list.html
+0
-2
asset_list.html
apps/assets/templates/assets/asset_list.html
+2
-2
asset_update.html
apps/assets/templates/assets/asset_update.html
+0
-1
cluster_assets.html
apps/assets/templates/assets/cluster_assets.html
+9
-4
cluster_create_update.html
apps/assets/templates/assets/cluster_create_update.html
+6
-7
cluster_detail.html
apps/assets/templates/assets/cluster_detail.html
+4
-4
cluster_list.html
apps/assets/templates/assets/cluster_list.html
+1
-1
system_user_asset.html
apps/assets/templates/assets/system_user_asset.html
+3
-3
system_user_detail.html
apps/assets/templates/assets/system_user_detail.html
+13
-1
user_asset_list.html
apps/assets/templates/assets/user_asset_list.html
+1
-2
api_urls.py
apps/assets/urls/api_urls.py
+4
-2
admin_user.py
apps/assets/views/admin_user.py
+13
-22
asset.py
apps/assets/views/asset.py
+13
-7
cluster.py
apps/assets/views/cluster.py
+13
-8
group.py
apps/assets/views/group.py
+17
-26
system_user.py
apps/assets/views/system_user.py
+15
-31
const.py
apps/common/const.py
+8
-0
utils.py
apps/common/utils.py
+2
-2
middleware.py
apps/jumpserver/middleware.py
+30
-10
settings.py
apps/jumpserver/settings.py
+4
-3
urls.py
apps/jumpserver/urls.py
+1
-1
django.mo
apps/locale/zh/LC_MESSAGES/django.mo
+0
-0
django.po
apps/locale/zh/LC_MESSAGES/django.po
+0
-0
api.py
apps/ops/api.py
+14
-1
hands.py
apps/ops/hands.py
+2
-1
models.py
apps/ops/models.py
+1
-0
adhoc_detail.html
apps/ops/templates/ops/adhoc_detail.html
+2
-2
adhoc_history.html
apps/ops/templates/ops/adhoc_history.html
+2
-2
adhoc_history_detail.html
apps/ops/templates/ops/adhoc_history_detail.html
+2
-2
task_adhoc.html
apps/ops/templates/ops/task_adhoc.html
+2
-2
task_detail.html
apps/ops/templates/ops/task_detail.html
+3
-3
task_history.html
apps/ops/templates/ops/task_history.html
+2
-2
task_list.html
apps/ops/templates/ops/task_list.html
+24
-1
api_urls.py
apps/ops/urls/api_urls.py
+4
-1
views.py
apps/ops/views.py
+8
-7
forms.py
apps/perms/forms.py
+28
-8
asset_permission_asset.html
apps/perms/templates/perms/asset_permission_asset.html
+2
-13
asset_permission_detail.html
apps/perms/templates/perms/asset_permission_detail.html
+20
-10
asset_permission_list.html
apps/perms/templates/perms/asset_permission_list.html
+4
-2
asset_permission_user.html
apps/perms/templates/perms/asset_permission_user.html
+2
-14
api_urls.py
apps/perms/urls/api_urls.py
+1
-3
views.py
apps/perms/views.py
+3
-57
jumpserver.js
apps/static/js/jumpserver.js
+11
-2
_base_create_update.html
apps/templates/_base_create_update.html
+2
-2
_base_list.html
apps/templates/_base_list.html
+2
-2
_header_bar.html
apps/templates/_header_bar.html
+13
-14
_user_profile.html
apps/templates/_user_profile.html
+7
-4
api.py
apps/terminal/api.py
+1
-2
forms.py
apps/terminal/forms.py
+0
-1
models.py
apps/terminal/models.py
+1
-0
session_detail.html
apps/terminal/templates/terminal/session_detail.html
+15
-15
session_list.html
apps/terminal/templates/terminal/session_list.html
+3
-1
terminal_detail.html
apps/terminal/templates/terminal/terminal_detail.html
+2
-2
terminal_list.html
apps/terminal/templates/terminal/terminal_list.html
+0
-1
terminal_update.html
apps/terminal/templates/terminal/terminal_update.html
+2
-2
session.py
apps/terminal/views/session.py
+4
-4
api.py
apps/users/api.py
+1
-1
forms.py
apps/users/forms.py
+10
-5
user.py
apps/users/models/user.py
+6
-2
user_detail.html
apps/users/templates/users/user_detail.html
+4
-4
user_group_create_update.html
apps/users/templates/users/user_group_create_update.html
+5
-17
user_group_detail.html
apps/users/templates/users/user_group_detail.html
+4
-5
user_group_granted_asset.html
apps/users/templates/users/user_group_granted_asset.html
+2
-2
user_list.html
apps/users/templates/users/user_list.html
+1
-1
group.py
apps/users/views/group.py
+6
-16
login.py
apps/users/views/login.py
+3
-1
user.py
apps/users/views/user.py
+7
-17
No files found.
apps/assets/api.py
View file @
7f3d32a8
...
...
@@ -26,7 +26,7 @@ from .hands import IsSuperUser, IsValidUser, IsSuperUserOrAppUser, \
get_user_granted_assets
from
.models
import
AssetGroup
,
Asset
,
Cluster
,
SystemUser
,
AdminUser
from
.
import
serializers
from
.tasks
import
update_asset_hardware_info_manual
,
test_admin_user_connectability_
uti
l
,
\
from
.tasks
import
update_asset_hardware_info_manual
,
test_admin_user_connectability_
manua
l
,
\
test_asset_connectability_manual
,
push_system_user_to_cluster_assets_manual
,
\
test_system_user_connectability_manual
...
...
@@ -40,18 +40,14 @@ class AssetViewSet(IDInFilterMixin, BulkModelViewSet):
"""
queryset
=
Asset
.
objects
.
all
()
serializer_class
=
serializers
.
AssetSerializer
permission_classes
=
(
Is
Valid
User
,)
permission_classes
=
(
Is
SuperUserOrApp
User
,)
def
get_queryset
(
self
):
if
self
.
request
.
user
.
is_superuser
or
self
.
request
.
user
.
is_app
:
queryset
=
super
()
.
get_queryset
()
else
:
assets_granted
=
get_user_granted_assets
(
self
.
request
.
user
)
queryset
=
self
.
queryset
.
filter
(
id__in
=
[
asset
.
id
for
asset
in
assets_granted
])
queryset
=
super
()
.
get_queryset
()
cluster_id
=
self
.
request
.
query_params
.
get
(
'cluster_id'
)
asset_group_id
=
self
.
request
.
query_params
.
get
(
'asset_group_id'
)
admin_user_id
=
self
.
request
.
query_params
.
get
(
'admin_user_id'
)
system_user_id
=
self
.
request
.
query_params
.
get
(
'system_user_id'
)
if
cluster_id
:
queryset
=
queryset
.
filter
(
cluster__id
=
cluster_id
)
...
...
@@ -62,6 +58,23 @@ class AssetViewSet(IDInFilterMixin, BulkModelViewSet):
assets_direct
=
[
asset
.
id
for
asset
in
admin_user
.
asset_set
.
all
()]
clusters
=
[
cluster
.
id
for
cluster
in
admin_user
.
cluster_set
.
all
()]
queryset
=
queryset
.
filter
(
Q
(
cluster__id__in
=
clusters
)
|
Q
(
id__in
=
assets_direct
))
if
system_user_id
:
system_user
=
get_object_or_404
(
SystemUser
,
id
=
system_user_id
)
clusters
=
system_user
.
get_clusters
()
queryset
=
queryset
.
filter
(
cluster__in
=
clusters
)
return
queryset
class
UserAssetListView
(
generics
.
ListAPIView
):
queryset
=
Asset
.
objects
.
all
()
serializer_class
=
serializers
.
AssetSerializer
permission_classes
=
(
IsValidUser
,)
def
get_queryset
(
self
):
assets_granted
=
get_user_granted_assets
(
self
.
request
.
user
)
queryset
=
self
.
queryset
.
filter
(
id__in
=
[
asset
.
id
for
asset
in
assets_granted
]
)
return
queryset
...
...
@@ -99,15 +112,6 @@ class GroupAddAssetsApi(generics.UpdateAPIView):
return
Response
({
'error'
:
serializer
.
errors
},
status
=
400
)
class
ClusterUpdateAssetsApi
(
generics
.
RetrieveUpdateAPIView
):
"""
Cluster update asset member
"""
queryset
=
Cluster
.
objects
.
all
()
serializer_class
=
serializers
.
ClusterUpdateAssetsSerializer
permission_classes
=
(
IsSuperUser
,)
class
ClusterViewSet
(
IDInFilterMixin
,
BulkModelViewSet
):
"""
Cluster api set, for add,delete,update,list,retrieve resource
...
...
@@ -117,7 +121,6 @@ class ClusterViewSet(IDInFilterMixin, BulkModelViewSet):
permission_classes
=
(
IsSuperUser
,)
# TOdo
class
ClusterTestAssetsAliveApi
(
generics
.
RetrieveAPIView
):
"""
Test cluster asset can connect using admin user or not
...
...
@@ -127,6 +130,9 @@ class ClusterTestAssetsAliveApi(generics.RetrieveAPIView):
def
retrieve
(
self
,
request
,
*
args
,
**
kwargs
):
cluster
=
self
.
get_object
()
admin_user
=
cluster
.
admin_user
test_admin_user_connectability_manual
.
delay
(
admin_user
)
return
Response
(
"Task has been send, seen left assets status"
)
class
ClusterAddAssetsApi
(
generics
.
UpdateAPIView
):
...
...
@@ -256,7 +262,7 @@ class AdminUserTestConnectiveApi(generics.RetrieveAPIView):
def
retrieve
(
self
,
request
,
*
args
,
**
kwargs
):
admin_user
=
self
.
get_object
()
test_admin_user_connectability_
uti
l
.
delay
(
admin_user
)
test_admin_user_connectability_
manua
l
.
delay
(
admin_user
)
return
Response
({
"msg"
:
"Task created"
})
...
...
This diff is collapsed.
Click to expand it.
apps/assets/forms.py
View file @
7f3d32a8
...
...
@@ -36,7 +36,7 @@ class AssetCreateForm(forms.ModelForm):
def
clean_admin_user
(
self
):
cluster
=
self
.
cleaned_data
.
get
(
'cluster'
)
admin_user
=
self
.
cleaned_data
.
get
(
'admin_user'
)
if
not
cluster
.
admin_user
and
not
admin_user
:
if
not
admin_user
and
(
cluster
and
not
cluster
.
admin_user
)
:
raise
forms
.
ValidationError
(
_
(
"You need set a admin user if cluster not have"
))
return
self
.
cleaned_data
[
'admin_user'
]
...
...
@@ -64,7 +64,7 @@ class AssetUpdateForm(forms.ModelForm):
def
clean_admin_user
(
self
):
cluster
=
self
.
cleaned_data
.
get
(
'cluster'
)
admin_user
=
self
.
cleaned_data
.
get
(
'admin_user'
)
if
not
cluster
.
admin_user
and
not
admin_user
:
if
not
admin_user
and
(
cluster
and
not
cluster
.
admin_user
)
:
raise
forms
.
ValidationError
(
_
(
"You need set a admin user if cluster not have"
))
return
self
.
cleaned_data
[
'admin_user'
]
...
...
@@ -124,20 +124,25 @@ class AssetGroupForm(forms.ModelForm):
label
=
_
(
'Asset'
),
required
=
False
,
widget
=
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select assets'
)}
)
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select assets'
)}
)
)
def
__init__
(
self
,
*
args
,
**
kwargs
):
if
kwargs
.
get
(
'instance'
,
None
):
def
__init__
(
self
,
**
kwargs
):
instance
=
kwargs
.
get
(
'instance'
)
if
instance
:
initial
=
kwargs
.
get
(
'initial'
,
{})
initial
[
'assets'
]
=
kwargs
[
'instance'
]
.
assets
.
all
()
super
(
AssetGroupForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
initial
.
update
({
'assets'
:
instance
.
assets
.
all
(),
})
kwargs
[
'initial'
]
=
initial
super
()
.
__init__
(
**
kwargs
)
def
_save_m2m
(
self
):
super
(
AssetGroupForm
,
self
)
.
_save_m2m
(
)
assets
=
self
.
cleaned_data
[
'assets'
]
self
.
instance
.
assets
.
clear
(
)
self
.
instance
.
assets
.
add
(
*
tuple
(
assets
))
def
save
(
self
,
commit
=
True
):
group
=
super
()
.
save
(
commit
=
commit
)
assets
=
self
.
cleaned_data
[
'assets'
]
group
.
assets
.
set
(
assets
)
return
group
class
Meta
:
model
=
AssetGroup
...
...
@@ -150,10 +155,19 @@ class AssetGroupForm(forms.ModelForm):
class
ClusterForm
(
forms
.
ModelForm
):
system_users
=
forms
.
ModelMultipleChoiceField
(
queryset
=
SystemUser
.
objects
.
all
(),
widget
=
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select system users'
)}
),
label
=
_
(
'System users'
),
required
=
False
,
help_text
=
_
(
"Selected system users will be create at cluster assets"
),
)
class
Meta
:
model
=
Cluster
fields
=
[
'name'
,
"bandwidth"
,
"operator"
,
'contact'
,
'admin_user'
,
fields
=
[
'name'
,
"bandwidth"
,
"operator"
,
'contact'
,
'admin_user'
,
'system_users'
,
'phone'
,
'address'
,
'intranet'
,
'extranet'
,
'comment'
]
widgets
=
{
'name'
:
forms
.
TextInput
(
attrs
=
{
'placeholder'
:
_
(
'Name'
)}),
...
...
@@ -162,9 +176,21 @@ class ClusterForm(forms.ModelForm):
}
help_texts
=
{
'name'
:
'* required'
,
'admin_user'
:
'The assets of this cluster will use this admin user as his admin user'
,
'admin_user'
:
_
(
"Cluster level admin user"
)
,
}
def
__init__
(
self
,
*
args
,
**
kwargs
):
if
kwargs
.
get
(
'instance'
,
None
):
initial
=
kwargs
.
get
(
'initial'
,
{})
initial
[
'system_users'
]
=
kwargs
[
'instance'
]
.
systemuser_set
.
all
()
super
()
.
__init__
(
*
args
,
**
kwargs
)
def
save
(
self
,
commit
=
True
):
instance
=
super
()
.
save
(
commit
=
commit
)
system_users
=
self
.
cleaned_data
[
'system_users'
]
instance
.
systemuser_set
.
set
(
system_users
)
return
instance
class
AdminUserForm
(
forms
.
ModelForm
):
# Form field name can not start with `_`, so redefine it,
...
...
@@ -172,9 +198,10 @@ class AdminUserForm(forms.ModelForm):
widget
=
forms
.
PasswordInput
,
max_length
=
128
,
strip
=
True
,
required
=
False
,
help_text
=
_
(
'Password or private key password'
),
label
=
_
(
"Password"
),
)
# Need use upload private key file except paste private key content
private_key_file
=
forms
.
FileField
(
required
=
False
)
private_key_file
=
forms
.
FileField
(
required
=
False
,
label
=
_
(
"Private key"
)
)
def
save
(
self
,
commit
=
True
):
# Because we define custom field, so we need rewrite :method: `save`
...
...
@@ -204,12 +231,14 @@ class AdminUserForm(forms.ModelForm):
return
private_key_file
def
clean
(
self
):
super
()
.
clean
()
password
=
self
.
cleaned_data
[
'password'
]
private_key_file
=
self
.
cleaned_data
.
get
(
'private_key_file'
,
''
)
if
not
self
.
instance
and
not
(
password
or
private_key_file
):
raise
forms
.
ValidationError
(
_
(
'Password and private key file must be input one'
))
if
not
password
and
not
private_key_file
:
raise
forms
.
ValidationError
(
_
(
'Password and private key file must be input one'
))
class
Meta
:
model
=
AdminUser
...
...
@@ -229,9 +258,10 @@ class SystemUserForm(forms.ModelForm):
# Admin user assets define, let user select, save it in form not in view
auto_generate_key
=
forms
.
BooleanField
(
initial
=
True
,
required
=
False
)
# Form field name can not start with `_`, so redefine it,
password
=
forms
.
CharField
(
widget
=
forms
.
PasswordInput
,
required
=
False
,
max_length
=
128
,
strip
=
True
)
password
=
forms
.
CharField
(
widget
=
forms
.
PasswordInput
,
required
=
False
,
max_length
=
128
,
strip
=
True
,
label
=
_
(
"Password"
))
# Need use upload private key file except paste private key content
private_key_file
=
forms
.
FileField
(
required
=
False
)
private_key_file
=
forms
.
FileField
(
required
=
False
,
label
=
_
(
"Private key"
)
)
def
save
(
self
,
commit
=
True
):
# Because we define custom field, so we need rewrite :method: `save`
...
...
@@ -278,15 +308,18 @@ class SystemUserForm(forms.ModelForm):
'name'
:
forms
.
TextInput
(
attrs
=
{
'placeholder'
:
_
(
'Name'
)}),
'username'
:
forms
.
TextInput
(
attrs
=
{
'placeholder'
:
_
(
'Username'
)}),
'cluster'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
' Select clusters'
)}),
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
' Select clusters'
)
}
),
}
help_texts
=
{
'name'
:
'* required'
,
'username'
:
'* required'
,
'cluster'
:
'If auto push checked, system user will be create at cluster assets'
,
'auto_push'
:
'Auto push system user to asset'
,
'priority'
:
'High level will be using login asset as default, if user was granted more than 2 system user'
,
'cluster'
:
_
(
'If auto push checked, system user will be create at cluster assets'
)
,
'auto_push'
:
_
(
'Auto push system user to asset'
)
,
'priority'
:
_
(
'High level will be using login asset as default, if user was granted more than 2 system user'
)
,
}
...
...
This diff is collapsed.
Click to expand it.
apps/assets/models/asset.py
View file @
7f3d32a8
...
...
@@ -18,6 +18,16 @@ __all__ = ['Asset']
logger
=
logging
.
getLogger
(
__name__
)
def
default_cluster
():
from
.cluster
import
Cluster
name
=
"Default"
defaults
=
{
"name"
:
name
}
cluster
,
created
=
Cluster
.
objects
.
get_or_create
(
defaults
=
defaults
,
name
=
name
)
return
cluster
.
id
class
Asset
(
models
.
Model
):
# Todo: Move them to settings
STATUS_CHOICES
=
(
...
...
@@ -44,7 +54,7 @@ class Asset(models.Model):
hostname
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
'Hostname'
))
port
=
models
.
IntegerField
(
default
=
22
,
verbose_name
=
_
(
'Port'
))
groups
=
models
.
ManyToManyField
(
AssetGroup
,
blank
=
True
,
related_name
=
'assets'
,
verbose_name
=
_
(
'Asset groups'
))
cluster
=
models
.
ForeignKey
(
Cluster
,
blank
=
True
,
null
=
True
,
related_name
=
'assets'
,
on_delete
=
models
.
SET_NULL
,
verbose_name
=
_
(
'Cluster'
))
cluster
=
models
.
ForeignKey
(
Cluster
,
related_name
=
'assets'
,
default
=
default_cluster
,
on_delete
=
models
.
SET_DEFAULT
,
verbose_name
=
_
(
'Cluster'
))
is_active
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
'Is active'
))
type
=
models
.
CharField
(
choices
=
TYPE_CHOICES
,
max_length
=
16
,
blank
=
True
,
null
=
True
,
default
=
'Server'
,
verbose_name
=
_
(
'Asset type'
),)
env
=
models
.
CharField
(
choices
=
ENV_CHOICES
,
max_length
=
8
,
blank
=
True
,
null
=
True
,
default
=
'Prod'
,
verbose_name
=
_
(
'Asset environment'
),)
...
...
@@ -158,6 +168,7 @@ class Asset(models.Model):
class
Meta
:
unique_together
=
(
'ip'
,
'port'
)
verbose_name
=
_
(
"Asset"
)
@classmethod
def
generate_fake
(
cls
,
count
=
100
):
...
...
This diff is collapsed.
Click to expand it.
apps/assets/models/cluster.py
View file @
7f3d32a8
...
...
@@ -37,6 +37,7 @@ class Cluster(models.Model):
class
Meta
:
ordering
=
[
'name'
]
verbose_name
=
_
(
"Cluster"
)
@classmethod
def
generate_fake
(
cls
,
count
=
5
):
...
...
This diff is collapsed.
Click to expand it.
apps/assets/models/group.py
View file @
7f3d32a8
...
...
@@ -27,6 +27,7 @@ class AssetGroup(models.Model):
class
Meta
:
ordering
=
[
'name'
]
verbose_name
=
_
(
"Asset group"
)
@classmethod
def
initial
(
cls
):
...
...
This diff is collapsed.
Click to expand it.
apps/assets/models/user.py
View file @
7f3d32a8
...
...
@@ -81,7 +81,11 @@ class AssetUser(models.Model):
@property
def
public_key
(
self
):
return
signer
.
unsign
(
self
.
_public_key
)
key
=
signer
.
unsign
(
self
.
_public_key
)
if
key
:
return
key
else
:
return
None
@property
def
public_key_obj
(
self
):
...
...
@@ -170,7 +174,6 @@ class AdminUser(AssetUser):
info
=
None
return
info
def
get_related_assets
(
self
):
assets
=
[]
for
cluster
in
self
.
cluster_set
.
all
():
...
...
@@ -184,6 +187,7 @@ class AdminUser(AssetUser):
class
Meta
:
ordering
=
[
'name'
]
verbose_name
=
_
(
"Admin user"
)
@classmethod
def
generate_fake
(
cls
,
count
=
10
):
...
...
@@ -224,7 +228,7 @@ class SystemUser(AssetUser):
def
get_clusters_assets
(
self
):
from
.asset
import
Asset
clusters
=
self
.
cluster
.
all
()
clusters
=
self
.
get_clusters
()
return
Asset
.
objects
.
filter
(
cluster__in
=
clusters
)
def
get_clusters
(
self
):
...
...
@@ -262,6 +266,7 @@ class SystemUser(AssetUser):
class
Meta
:
ordering
=
[
'name'
]
verbose_name
=
_
(
"System user"
)
@classmethod
def
generate_fake
(
cls
,
count
=
10
):
...
...
This diff is collapsed.
Click to expand it.
apps/assets/serializers.py
View file @
7f3d32a8
...
...
@@ -64,6 +64,7 @@ class AdminUserSerializer(serializers.ModelSerializer):
"""
assets_amount
=
serializers
.
SerializerMethodField
()
unreachable_amount
=
serializers
.
SerializerMethodField
()
reachable_amount
=
serializers
.
SerializerMethodField
()
class
Meta
:
model
=
AdminUser
...
...
@@ -75,7 +76,15 @@ class AdminUserSerializer(serializers.ModelSerializer):
if
data
:
return
len
(
data
.
get
(
'dark'
))
else
:
return
'Unknown'
return
0
@staticmethod
def
get_reachable_amount
(
obj
):
data
=
cache
.
get
(
ADMIN_USER_CONN_CACHE_KEY
.
format
(
obj
.
name
))
if
data
:
return
len
(
data
.
get
(
'contacted'
))
else
:
return
0
@staticmethod
def
get_assets_amount
(
obj
):
...
...
@@ -183,7 +192,7 @@ class AssetGrantedSerializer(serializers.ModelSerializer):
class
Meta
(
object
):
model
=
Asset
fields
=
(
"id"
,
"hostname"
,
"ip"
,
"port"
,
"system_users_granted"
,
"is_inherited"
,
"is_active"
,
"system_users_join"
,
"is_inherited"
,
"is_active"
,
"system_users_join"
,
"os"
,
"platform"
,
"comment"
,)
@staticmethod
...
...
This diff is collapsed.
Click to expand it.
apps/assets/signals_handler.py
View file @
7f3d32a8
...
...
@@ -27,16 +27,17 @@ def test_asset_conn_on_created(asset):
def
push_cluster_system_users_to_asset
(
asset
):
logger
.
info
(
"Push cluster system user to asset: {}"
.
format
(
asset
))
task_name
=
_
(
"Push cluster system users to asset"
)
system_users
=
asset
.
cluster
.
systemuser_set
.
all
()
push_system_user_util
.
delay
(
system_users
,
[
asset
],
task_name
)
if
asset
.
cluster
:
logger
.
info
(
"Push cluster system user to asset: {}"
.
format
(
asset
))
task_name
=
_
(
"Push cluster system users to asset"
)
system_users
=
asset
.
cluster
.
systemuser_set
.
all
()
push_system_user_util
.
delay
(
system_users
,
[
asset
],
task_name
)
@receiver
(
post_save
,
sender
=
Asset
,
dispatch_uid
=
"my_unique_identifier"
)
def
on_asset_created
(
sender
,
instance
=
None
,
created
=
False
,
**
kwargs
):
if
instance
and
created
:
logger
.
info
(
"Asset `` create signal received"
.
format
(
instance
))
logger
.
info
(
"Asset `
{}
` create signal received"
.
format
(
instance
))
update_asset_hardware_info_on_created
(
instance
)
test_asset_conn_on_created
(
instance
)
push_cluster_system_users_to_asset
(
instance
)
...
...
@@ -77,7 +78,7 @@ def on_system_user_created_or_updated(sender, instance=None, **kwargs):
@receiver
(
post_init
,
sender
=
Cluster
,
dispatch_uid
=
"my_unique_identifier"
)
def
on_cluster_init
(
sender
,
instance
,
**
kwargs
):
instance
.
__original_assets
=
tuple
(
instance
.
assets
.
values_list
(
'pk'
,
flat
=
True
))
# instance.__origin_system_users = tuple(instance.systemuser_set.all(
))
instance
.
__origin_system_users
=
tuple
(
instance
.
systemuser_set
.
values_list
(
'pk'
,
flat
=
True
))
@receiver
(
post_save
,
sender
=
Cluster
,
dispatch_uid
=
"my_unique_identifier"
)
...
...
@@ -103,11 +104,11 @@ def on_cluster_assets_changed(sender, instance, **kwargs):
push_system_user_util
.
delay
(
system_users
,
assets
,
task_name
)
@receiver
(
post_save
,
sender
=
Cluster
,
dispatch_uid
=
"my_unique_identifier"
)
@receiver
(
post_save
,
sender
=
Cluster
,
dispatch_uid
=
"my_unique_identifier
2
"
)
def
on_cluster_system_user_changed
(
sender
,
instance
,
**
kwargs
):
system_users_origin
=
instance
.
__origin_system_users
system_user_new
=
instance
.
systemuser_set
.
values_list
(
'pk'
,
flat
=
True
)
system_users_added
=
set
(
system_user_new
)
-
s
ystem_users_origin
system_users_added
=
set
(
system_user_new
)
-
s
et
(
system_users_origin
)
if
system_users_added
:
logger
.
debug
(
"Receive cluster change system users signal"
)
system_users
=
[]
...
...
This diff is collapsed.
Click to expand it.
apps/assets/tasks.py
View file @
7f3d32a8
...
...
@@ -25,7 +25,7 @@ disk_pattern = re.compile(r'^hd|sd|xvd')
@shared_task
def
set_assets_hardware_info
(
result
,
**
kwargs
):
"""
U
n
sing ops task run result, to update asset info
Using ops task run result, to update asset info
@shared_task must be exit, because we using it as a task callback, is must
be a celery task also
...
...
@@ -209,8 +209,11 @@ def test_asset_connectability_util(asset, task_name=None):
from
ops.utils
import
update_or_create_ansible_task
if
task_name
is
None
:
task_name
=
"Test asset connectability"
task_name
=
_
(
"Test asset connectability"
)
hosts
=
[
asset
.
hostname
]
if
not
hosts
:
logger
.
info
(
"No hosts, passed"
)
return
{}
tasks
=
const
.
TEST_ADMIN_USER_CONN_TASKS
task
,
created
=
update_or_create_ansible_task
(
task_name
=
task_name
,
hosts
=
hosts
,
tasks
=
tasks
,
pattern
=
'all'
,
...
...
@@ -262,6 +265,9 @@ def test_system_user_connectability_util(system_user, task_name):
assets
=
system_user
.
get_clusters_assets
()
hosts
=
[
asset
.
hostname
for
asset
in
assets
]
tasks
=
const
.
TEST_SYSTEM_USER_CONN_TASKS
if
not
hosts
:
logger
.
info
(
"No hosts, passed"
)
return
{}
task
,
created
=
update_or_create_ansible_task
(
task_name
,
hosts
=
hosts
,
tasks
=
tasks
,
pattern
=
'all'
,
options
=
const
.
TASK_OPTIONS
,
...
...
@@ -274,7 +280,7 @@ def test_system_user_connectability_util(system_user, task_name):
@shared_task
def
test_system_user_connectability_manual
(
system_user
):
task_name
=
"Test system user connectability: {}"
.
format
(
system_user
)
task_name
=
_
(
"Test system user connectability: {}"
)
.
format
(
system_user
)
return
test_system_user_connectability_util
(
system_user
,
task_name
)
...
...
@@ -303,6 +309,10 @@ def test_system_user_connectability_period():
#### Push system user tasks ####
def
get_push_system_user_tasks
(
system_user
):
# Set root as system user is dangerous
if
system_user
.
username
==
"root"
:
return
[]
tasks
=
[
{
'name'
:
'Add user {}'
.
format
(
system_user
.
username
),
...
...
@@ -310,7 +320,7 @@ def get_push_system_user_tasks(system_user):
'module'
:
'user'
,
'args'
:
'name={} shell={} state=present password={}'
.
format
(
system_user
.
username
,
system_user
.
shell
,
encrypt_password
(
system_user
.
password
),
encrypt_password
(
system_user
.
password
,
salt
=
"K3mIlKK"
),
),
}
},
...
...
@@ -346,11 +356,14 @@ def push_system_user_util(system_users, assets, task_name):
for
system_user
in
system_users
:
tasks
.
extend
(
get_push_system_user_tasks
(
system_user
))
print
(
"Task: "
,
tasks
)
if
not
tasks
:
return
logger
.
info
(
"Not tasks, passed"
)
return
{}
hosts
=
[
asset
.
hostname
for
asset
in
assets
]
if
not
hosts
:
logger
.
info
(
"Not hosts, passed"
)
return
{}
task
,
created
=
update_or_create_ansible_task
(
task_name
=
task_name
,
hosts
=
hosts
,
tasks
=
tasks
,
pattern
=
'all'
,
options
=
const
.
TASK_OPTIONS
,
run_as_admin
=
True
,
created_by
=
'System'
...
...
@@ -381,8 +394,8 @@ def push_system_user_period():
for
system_user
in
system_users
:
tasks
.
extend
(
get_push_system_user_tasks
(
system_user
))
task_name
=
_
(
"Push
system user to cluster assets period: {}->
{}"
)
.
format
(
cluster
.
name
,
', '
.
join
(
s
.
name
for
s
in
system_users
)
task_name
=
_
(
"Push
cluster system users to assets period:
{}"
)
.
format
(
cluster
.
name
)
hosts
=
[
asset
.
hostname
for
asset
in
cluster
.
assets
.
all
()]
update_or_create_ansible_task
(
...
...
This diff is collapsed.
Click to expand it.
apps/assets/templates/assets/_system_user.html
View file @
7f3d32a8
...
...
@@ -3,8 +3,8 @@
{% 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>
<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 %}
...
...
This diff is collapsed.
Click to expand it.
apps/assets/templates/assets/admin_user_assets.html
View file @
7f3d32a8
...
...
@@ -21,11 +21,11 @@
<a
href=
"{% url 'assets:admin-user-assets' pk=admin_user.pk %}"
class=
"text-center"
><i
class=
"fa fa-laptop"
></i>
{% trans 'Assets list' %}
</a>
</li>
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'assets:admin-user-update' pk=admin_user.id %}"
><i
class=
"fa fa-edit"
></i>
Update
</a>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'assets:admin-user-update' pk=admin_user.id %}"
><i
class=
"fa fa-edit"
></i>
{% trans 'Update' %}
</a>
</li>
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline btn-danger btn-delete-admin-user"
>
<i
class=
"fa fa-
edit"
></i>
Delete
<i
class=
"fa fa-
trash-o"
></i>
{% trans 'Delete' %}
</a>
</li>
</ul>
...
...
@@ -60,7 +60,7 @@
<th>
{% trans 'IP' %}
</th>
<th>
{% trans 'Port' %}
</th>
<th>
{% trans 'Type' %}
</th>
<th>
{% trans '
Aliv
e' %}
</th>
<th>
{% trans '
Reachabl
e' %}
</th>
</tr>
</thead>
<tbody>
...
...
@@ -144,7 +144,7 @@ $(document).ready(function () {
url
:
the_url
,
error
:
error
,
method
:
'GET'
,
success_message
:
"{% trans
"
Task
has
been
send
,
seen
left
asset
status
"
%}"
success_message
:
"{% trans
'Task has been send, seen left asset status'
%}"
});
})
</script>
...
...
This diff is collapsed.
Click to expand it.
apps/assets/templates/assets/admin_user_create_update.html
View file @
7f3d32a8
...
...
@@ -3,8 +3,8 @@
{% 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>
<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 %}
...
...
This diff is collapsed.
Click to expand it.
apps/assets/templates/assets/admin_user_detail.html
View file @
7f3d32a8
...
...
@@ -21,11 +21,11 @@
<a
href=
"{% url 'assets:admin-user-assets' pk=admin_user.pk %}"
class=
"text-center"
><i
class=
"fa fa-laptop"
></i>
{% trans 'Assets list' %}
</a>
</li>
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'assets:admin-user-update' pk=admin_user.id %}"
><i
class=
"fa fa-edit"
></i>
Update
</a>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'assets:admin-user-update' pk=admin_user.id %}"
><i
class=
"fa fa-edit"
></i>
{% trans 'Update' %}
</a>
</li>
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline btn-danger btn-delete-admin-user"
>
<i
class=
"fa fa-
edit"
></i>
Delete
<i
class=
"fa fa-
trash-o"
></i>
{% trans 'Delete' %}
</a>
</li>
</ul>
...
...
@@ -133,7 +133,6 @@ function bindToCluster(clusters) {
$
(
'.select2-selection__rendered'
).
empty
();
$
(
'#cluster_selected'
).
val
(
''
);
$
.
map
(
jumpserver
.
cluster_selected
,
function
(
cluster_name
,
index
)
{
console
.
log
(
index
);
$
(
'#opt_'
+
index
).
remove
();
// change tr html of user groups.
$
(
'#table-clusters tbody'
).
append
(
...
...
This diff is collapsed.
Click to expand it.
apps/assets/templates/assets/admin_user_list.html
View file @
7f3d32a8
...
...
@@ -21,8 +21,10 @@
</th>
<th
class=
"text-center"
>
{% trans 'Name' %}
</th>
<th
class=
"text-center"
>
{% trans 'Username' %}
</th>
<th
class=
"text-center"
>
{% trans 'Asset num' %}
</th>
<th
class=
"text-center"
>
{% trans 'Asset' %}
</th>
<th
class=
"text-center"
>
{% trans 'Reachable' %}
</th>
<th
class=
"text-center"
>
{% trans 'Unreachable' %}
</th>
<th
class=
"text-center"
>
{% trans 'Ratio' %}
</th>
<th
class=
"text-center"
>
{% trans 'Comment' %}
</th>
<th
class=
"text-center"
>
{% trans 'Action' %}
</th>
</tr>
...
...
@@ -41,17 +43,50 @@ $(document).ready(function(){
{
targets
:
1
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
detail_btn
=
'<a href="{% url "assets:admin-user-detail" pk=DEFAULT_PK %}">'
+
cellData
+
'</a>'
;
$
(
td
).
html
(
detail_btn
.
replace
(
'{{ DEFAULT_PK }}'
,
rowData
.
id
));
}},
}},
{
targets
:
4
,
createdCell
:
function
(
td
,
cellData
)
{
var
innerHtml
=
""
;
if
(
cellData
!==
0
)
{
innerHtml
=
"<span class='text-navy'>"
+
cellData
+
"</span>"
;
}
else
{
innerHtml
=
"<span>"
+
cellData
+
"</span>"
;
}
$
(
td
).
html
(
'<span href="javascript:void(0);" data-toggle="tooltip" title="'
+
cellData
+
'">'
+
innerHtml
+
'</span>'
);
}},
{
targets
:
5
,
createdCell
:
function
(
td
,
cellData
)
{
var
innerHtml
=
""
;
if
(
cellData
!==
0
)
{
innerHtml
=
"<span class='text-danger'>"
+
cellData
+
"</span>"
;
}
else
{
innerHtml
=
"<span>"
+
cellData
+
"</span>"
;
}
$
(
td
).
html
(
'<span href="javascript:void(0);" data-toggle="tooltip" title="'
+
cellData
+
'">'
+
innerHtml
+
'</span>'
);
}},
{
targets
:
6
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
{
#
var
script_btn
=
'<a href="{% url "assets:admin-user-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-primary">{% trans "Script" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
);
#
}
var
val
=
0
;
var
innerHtml
=
""
;
var
total
=
rowData
.
assets_amount
;
var
reachable
=
rowData
.
reachable_amount
;
if
(
total
!==
0
)
{
val
=
reachable
/
total
*
100
;
}
if
(
val
===
100
)
{
innerHtml
=
"<span class='text-navy'>"
+
val
+
"% </span>"
;
}
else
{
innerHtml
=
"<span class='text-danger'>"
+
val
+
"% </span>"
;
}
$
(
td
).
html
(
'<span href="javascript:void(0);" data-toggle="tooltip" title="'
+
cellData
+
'">'
+
innerHtml
+
'</span>'
);
}},
{
targets
:
8
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
update_btn
=
'<a href="{% url "assets:admin-user-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_admin_user_delete" data-uid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
);
{
#
$
(
td
).
html
(
script_btn
+
update_btn
+
del_btn
)
#
}
$
(
td
).
html
(
update_btn
+
del_btn
)
}}],
ajax_url
:
'{% url "api-assets:admin-user-list" %}'
,
columns
:
[{
data
:
function
(){
return
""
}},
{
data
:
"name"
},
{
data
:
"username"
},
{
data
:
"assets_amount"
},
{
data
:
"
unreachable_amount
"
},
{
data
:
"comment"
},
{
data
:
"id"
}]
{
data
:
"
reachable_amount"
},
{
data
:
"unreachable_amount"
},
{
data
:
"id
"
},
{
data
:
"comment"
},
{
data
:
"id"
}]
};
jumpserver
.
initDataTable
(
options
);
})
...
...
This diff is collapsed.
Click to expand it.
apps/assets/templates/assets/asset_detail.html
View file @
7f3d32a8
...
...
@@ -21,11 +21,11 @@
</li>
{% if user.is_superuser %}
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'assets:asset-update' pk=asset.id %}"
><i
class=
"fa fa-edit"
></i>
Update
</a>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'assets:asset-update' pk=asset.id %}"
><i
class=
"fa fa-edit"
></i>
{% trans 'Update' %}
</a>
</li>
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline btn-danger btn-delete-asset"
>
<i
class=
"fa fa-
edit"
></i>
Delete
<i
class=
"fa fa-
trash-o"
></i>
{% trans 'Delete' %}
</a>
</li>
{% endif %}
...
...
This diff is collapsed.
Click to expand it.
apps/assets/templates/assets/asset_group_create.html
View file @
7f3d32a8
{% extends 'base.html' %}
{% load i18n %}
{% extends '_base_create_update.html' %}
{% 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-10"
>
<div
class=
"ibox float-e-margins"
>
<div
id=
"ibox-content"
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>
{% load i18n %}
<div
class=
"ibox-content"
>
<div
class=
"panel blank-panel"
>
<div
class=
"panel-body"
>
<div
class=
"tab-content"
>
<form
id=
"groupForm"
method=
"post"
class=
"form-horizontal"
>
{% csrf_token %}
<h3
class=
"widget-head-color-box"
>
资产组信息
</h3>
{% bootstrap_field form.name layout="horizontal" %}
{% bootstrap_field form.comment layout="horizontal" %}
{#
<div
class=
"hr-line-dashed"
></div>
#}
{#
<h3
class=
"widget-head-color-box"
>
用户选择的资产
</h3>
#}
{#
<div
class=
"form-group"
>
#}
{#
<label
class=
"col-sm-2 control-label"
id=
"asset_on_count"
>
已选({{ assets_count }})
</label>
#}
{#
<div
class=
"col-sm-9"
id=
"asset_sed"
>
#}
{#
<div
class=
"form-asset-on"
id=
"add_asset"
>
#}
{#
<p
id=
"asset_on_p"
>
#}
{# {% for asset in assets_on_list %}#}
{#
<button
name=
'asset_hostname'
title=
'{{ asset.ip }}'
type=
'button'
class=
'btn btn-default btn-xs'
>
{{ asset.hostname }}
</button>
#}
{# {% endfor %}#}
{#
</p>
#}
{#
</div>
#}
{#
</div>
#}
{#
</div>
#}
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<div
class=
"col-sm-4 col-sm-offset-5"
>
<button
class=
"btn btn-white"
type=
"reset"
>
重置
</button>
<button
class=
"btn btn-primary"
type=
"submit"
>
提交
</button>
<div
id=
'box2'
>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% block form %}
<form
id=
"groupForm"
method=
"post"
class=
"form-horizontal"
>
{% csrf_token %}
{% bootstrap_field form.name layout="horizontal" %}
{% bootstrap_field form.assets 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>
</div>
<!-- 模态框(Modal) -->
<div
class=
"modal fade"
id=
"modal"
tabindex=
"-1"
role=
"dialog"
aria-labelledby=
"myModalLabel"
aria-hidden=
"true"
>
<div
class=
"modal-dialog modal-lg"
>
<div
class=
"modal-content"
id=
"box"
>
<!--此部分为主体内容,将远程加载进来-->
</div>
</div>
</div>
</form>
{% endblock %}
{% block custom_foot_js %}
<script
type=
"text/javascript"
>
$
(
document
).
ready
(
function
()
{
$
(
'.select2'
).
select2
();
$
(
'.select2-system-user'
).
select2
();
});
$
(
'#add_asset'
).
on
(
'click'
,
function
(){
$
(
'#modal'
).
modal
(
'show'
);
});
$
(
'#modal'
).
modal
({
show
:
false
,
backdrop
:
'static'
,
keyboard
:
'false'
,
remote
:
"{% url 'assets:asset-modal-list' %}?group_id={{ group_id }}"
});
$
(
'#modal'
).
on
(
'show.bs.modal'
,
function
(){
//alert('当调用show方法时,立即触发;')
$
(
'.select2'
).
select2
({
closeOnSelect
:
false
});
});
$
(
'#modal'
).
on
(
'shown.bs.modal'
,
function
(){
//alert('当弹窗完全加载完后,再触发;')
});
$
(
'#modal'
).
on
(
'hide.bs.modal'
,
function
(){
//alert('当关闭时,立即触发;')
});
$
(
'#modal'
).
on
(
'hidden.bs.modal'
,
function
(){
//alert('当关完全关闭后,再触发;')
});
$
(
'#modal'
).
on
(
'loaded.bs.modal'
,
function
(){
//alert('当远程数据加载完毕后,再触发;')
});
</script>
{% endblock %}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
apps/assets/templates/assets/asset_group_detail.html
View file @
7f3d32a8
...
...
@@ -3,8 +3,8 @@
{% 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>
<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"
>
...
...
@@ -15,7 +15,12 @@
<ul
class=
"nav nav-tabs"
>
<li
class=
"active"
><a
href=
""
class=
"text-center"
><i
class=
"fa fa-laptop"
></i>
{% trans 'Group assets' %}
</a></li>
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'assets:asset-group-update' pk=asset_group.id %}"
><i
class=
"fa fa-edit"
></i>
Update
</a>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'assets:asset-group-update' pk=asset_group.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>
...
...
@@ -212,7 +217,6 @@ $(document).ready(function () {
addAssets
(
assets_id
);
})
.
on
(
'click'
,
'.btn-leave-group'
,
function
()
{
var
$this
=
$
(
this
);
var
the_url
=
"{% url 'api-assets:group-update-assets' pk=asset_group.id %}"
;
...
...
@@ -223,9 +227,15 @@ $(document).ready(function () {
});
var
delete_asset_id
=
$
(
this
).
data
(
'aid'
);
assets
.
remove
(
delete_asset_id
);
console
.
log
(
assets
);
var
data
=
{
"assets"
:
assets
};
leaveGroup
(
$this
,
name
,
the_url
,
data
);
}).
on
(
'click'
,
'.btn-del'
,
function
()
{
var
$this
=
$
(
this
);
var
name
=
"{{ asset_group.name}}"
;
var
uid
=
"{{ asset_group.id }}"
;
var
the_url
=
'{% url "api-assets:asset-group-detail" pk=DEFAULT_PK %}'
.
replace
(
'{{ DEFAULT_PK }}'
,
uid
);
var
redirect_url
=
"{% url 'assets:asset-group-list' %}"
;
objectDelete
(
$this
,
name
,
the_url
,
redirect_url
);
})
...
...
This diff is collapsed.
Click to expand it.
apps/assets/templates/assets/asset_group_list.html
View file @
7f3d32a8
...
...
@@ -75,8 +75,6 @@ $(document).ready(function(){
return
false
;
}
var
the_url
=
'{% url "api-assets:asset-group-list" %}'
;
console
.
log
(
plain_id_list
);
console
.
log
(
the_url
);
function
doDelete
()
{
swal
({
title
:
"{% trans 'Are you sure?' %}"
,
...
...
This diff is collapsed.
Click to expand it.
apps/assets/templates/assets/asset_list.html
View file @
7f3d32a8
...
...
@@ -109,7 +109,7 @@ function initTable() {
$
(
document
).
ready
(
function
(){
initTable
();
})
.
on
(
'click'
,
'
#
btn_export'
,
function
()
{
.
on
(
'click'
,
'
.
btn_export'
,
function
()
{
var
$data_table
=
$
(
'#asset_list_table'
).
DataTable
();
var
rows
=
$data_table
.
rows
(
'.selected'
).
data
();
var
assets
=
[];
...
...
@@ -129,7 +129,7 @@ $(document).ready(function(){
}
})
})
.
on
(
'click'
,
'#btn_import'
,
function
()
{
.
on
(
'click'
,
'#btn_
asset_
import'
,
function
()
{
var
$form
=
$
(
'#fm_asset_import'
);
$form
.
find
(
'.help-block'
).
remove
();
function
success
(
data
)
{
...
...
This diff is collapsed.
Click to expand it.
apps/assets/templates/assets/asset_update.html
View file @
7f3d32a8
...
...
@@ -46,7 +46,6 @@
<div
class=
"hr-line-dashed"
></div>
<h3>
{% trans 'Other' %}
</h3>
{% bootstrap_field form.status layout="horizontal" %}
{% bootstrap_field form.env layout="horizontal" %}
{% bootstrap_field form.comment layout="horizontal" %}
{% bootstrap_field form.is_active layout="horizontal" %}
...
...
This diff is collapsed.
Click to expand it.
apps/assets/templates/assets/cluster_assets.html
View file @
7f3d32a8
...
...
@@ -3,8 +3,8 @@
{% 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>
<link
href=
"{% static
'css/plugins/select2/select2.min.css'
%}"
rel=
"stylesheet"
>
<script
src=
"{% static
'js/plugins/select2/select2.full.min.js'
%}"
></script>
<style
type=
"text/css"
>
</style>
...
...
@@ -94,7 +94,7 @@
<td
colspan=
"2"
>
<select
data-placeholder=
"{% trans 'Select asset' %}"
class=
"select2"
style=
"width: 100%"
multiple=
""
tabindex=
"4"
>
{% for asset in assets_remain %}
<option
value=
"{{ asset.id }}"
id=
"opt_{{ asset.id }}"
>
{{ asset.
ip}}:{{ asset.port
}}
</option>
<option
value=
"{{ asset.id }}"
id=
"opt_{{ asset.id }}"
>
{{ asset.
hostname
}}
</option>
{% endfor %}
</select>
</td>
...
...
@@ -204,7 +204,12 @@ $(document).ready(function () {
addAssets
(
assets_id
);
})
.
on
(
'click'
,
'#btn-test-assets'
,
function
()
{
console
.
log
(
'ok'
);
var
the_url
=
"{% url 'api-assets:cluster-test-connective' pk=cluster.id %}"
;
APIUpdateAttr
({
url
:
the_url
,
method
:
'GET'
,
success_message
:
"{% trans 'Task has been send, seen left assets status' %}"
});
})
</script>
{% endblock %}
This diff is collapsed.
Click to expand it.
apps/assets/templates/assets/cluster_create_update.html
View file @
7f3d32a8
...
...
@@ -3,8 +3,8 @@
{% 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>
<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"
>
...
...
@@ -40,6 +40,7 @@
<h3
class=
"widget-head-color-box"
>
{% trans 'Settings' %}
</h3>
{% bootstrap_field form.admin_user layout="horizontal" %}
{% bootstrap_field form.system_users layout="horizontal" %}
<div
class=
"hr-line-dashed"
></div>
<h3
class=
"widget-head-color-box"
>
{% trans 'Other' %}
</h3>
...
...
@@ -69,10 +70,7 @@
{% block custom_foot_js %}
<script>
$
(
document
).
ready
(
function
()
{
$
(
'.select2'
).
select2
({
dropdownAutoWidth
:
true
,
width
:
'auto'
});
})
$
(
'.select2'
).
select2
();
});
</script>
{% endblock %}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
apps/assets/templates/assets/cluster_detail.html
View file @
7f3d32a8
...
...
@@ -3,8 +3,8 @@
{% 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>
<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"
>
...
...
@@ -22,11 +22,11 @@
</a>
</li>
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'assets:cluster-update' pk=cluster.id %}"
><i
class=
"fa fa-edit"
></i>
Update
</a>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'assets:cluster-update' pk=cluster.id %}"
><i
class=
"fa fa-edit"
></i>
{% trans 'Update' %}
</a>
</li>
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline btn-danger btn-delete-cluster"
>
<i
class=
"fa fa-
edit"
></i>
Delete
<i
class=
"fa fa-
trash-o"
></i>
{% trans 'Delete' %}
</a>
</li>
</ul>
...
...
This diff is collapsed.
Click to expand it.
apps/assets/templates/assets/cluster_list.html
View file @
7f3d32a8
...
...
@@ -8,7 +8,7 @@
{% block table_search %}{% endblock %}
{% block table_container %}
<div
class=
"uc pull-left m-r-5"
>
<a
href=
"{% url "
assets:cluster-create
"
%}"
class=
"btn btn-sm btn-primary"
>
{% trans "Create
C
luster" %}
</a>
<a
href=
"{% url "
assets:cluster-create
"
%}"
class=
"btn btn-sm btn-primary"
>
{% trans "Create
c
luster" %}
</a>
</div>
<table
class=
"table table-striped table-bordered table-hover "
id=
"cluster_list_table"
>
<thead>
...
...
This diff is collapsed.
Click to expand it.
apps/assets/templates/assets/system_user_asset.html
View file @
7f3d32a8
...
...
@@ -3,8 +3,8 @@
{% 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>
<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"
>
...
...
@@ -22,7 +22,7 @@
</a>
</li>
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'assets:system-user-update' pk=system_user.id %}"
><i
class=
"fa fa-edit"
></i>
Update
</a>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'assets:system-user-update' pk=system_user.id %}"
><i
class=
"fa fa-edit"
></i>
{% trans 'Update' %}
</a>
</li>
</ul>
</div>
...
...
This diff is collapsed.
Click to expand it.
apps/assets/templates/assets/system_user_detail.html
View file @
7f3d32a8
...
...
@@ -23,7 +23,12 @@
</a>
</li>
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'assets:system-user-update' pk=system_user.id %}"
><i
class=
"fa fa-edit"
></i>
Update
</a>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'assets:system-user-update' pk=system_user.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>
...
...
@@ -259,6 +264,13 @@ $(document).ready(function () {
return
$
(
this
).
data
(
'gid'
);
}).
get
();
updateSystemUserCluster
(
clusters
);
}).
on
(
'click'
,
'.btn-del'
,
function
()
{
var
$this
=
$
(
this
);
var
name
=
"{{ system_user.name}}"
;
var
uid
=
"{{ system_user.id }}"
;
var
the_url
=
'{% url "api-assets:system-user-detail" pk=DEFAULT_PK %}'
.
replace
(
'{{ DEFAULT_PK }}'
,
uid
);
var
redirect_url
=
"{% url 'assets:system-user-list' %}"
;
objectDelete
(
$this
,
name
,
the_url
,
redirect_url
);
})
</script>
{% endblock %}
This diff is collapsed.
Click to expand it.
apps/assets/templates/assets/user_asset_list.html
View file @
7f3d32a8
...
...
@@ -42,7 +42,6 @@ function initTable() {
columnDefs
:
[
{
targets
:
1
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
{
%
url
'assets:asset-detail'
pk
=
DEFAULT_PK
as
the_url
%
}
console
.
log
(
'{{ the_url }}'
);
var
detail_btn
=
'<a href="{{ the_url }}">'
+
cellData
+
'</a>'
;
$
(
td
).
html
(
detail_btn
.
replace
(
'{{ DEFAULT_PK }}'
,
rowData
.
id
));
}},
...
...
@@ -67,7 +66,7 @@ function initTable() {
$
(
td
).
html
(
conn_btn
)
}}
],
ajax_url
:
'{% url "api-assets:asset-list" %}'
,
ajax_url
:
'{% url "api-assets:
user-
asset-list" %}'
,
columns
:
[
{
data
:
"id"
},
{
data
:
"hostname"
},
{
data
:
"ip"
},
{
data
:
"port"
},
{
data
:
"get_type_display"
},
{
data
:
"get_env_display"
},
{
data
:
"hardware_info"
},
...
...
This diff is collapsed.
Click to expand it.
apps/assets/urls/api_urls.py
View file @
7f3d32a8
...
...
@@ -21,16 +21,18 @@ urlpatterns = [
api
.
AssetRefreshHardwareApi
.
as_view
(),
name
=
'asset-refresh'
),
url
(
r'^v1/assets/(?P<pk>[0-9a-zA-Z\-]{36})/alive/$'
,
api
.
AssetAdminUserTestApi
.
as_view
(),
name
=
'asset-alive-test'
),
url
(
r'^v1/assets/user-assets/$'
,
api
.
UserAssetListView
.
as_view
(),
name
=
'user-asset-list'
),
# update the asset group, which add or delete the asset to the group
url
(
r'^v1/groups/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$'
,
api
.
GroupUpdateAssetsApi
.
as_view
(),
name
=
'group-update-assets'
),
url
(
r'^v1/groups/(?P<pk>[0-9a-zA-Z\-]{36})/assets/add/$'
,
api
.
GroupAddAssetsApi
.
as_view
(),
name
=
'group-add-assets'
),
# update the Cluster, and add or delete the assets to the Cluster
url
(
r'^v1/cluster/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$'
,
api
.
ClusterUpdateAssetsApi
.
as_view
(),
name
=
'cluster-update-assets'
),
url
(
r'^v1/cluster/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$'
,
api
.
ClusterAddAssetsApi
.
as_view
(),
name
=
'cluster-add-assets'
),
url
(
r'^v1/cluster/(?P<pk>[0-9a-zA-Z\-]{36})/assets/connective/$'
,
api
.
ClusterTestAssetsAliveApi
.
as_view
(),
name
=
'cluster-test-connective'
),
url
(
r'^v1/admin-user/(?P<pk>[0-9a-zA-Z\-]{36})/clusters/$'
,
api
.
AdminUserAddClustersApi
.
as_view
(),
name
=
'admin-user-add-clusters'
),
url
(
r'^v1/admin-user/(?P<pk>[0-9a-zA-Z\-]{36})/connective/$'
,
...
...
This diff is collapsed.
Click to expand it.
apps/assets/views/admin_user.py
View file @
7f3d32a8
...
...
@@ -2,20 +2,22 @@
from
__future__
import
absolute_import
,
unicode_literals
from
django.utils.translation
import
ugettext
as
_
from
django.conf
import
settings
from
django.views.generic
import
TemplateView
,
ListView
,
View
from
django.views.generic.edit
import
CreateView
,
DeleteView
,
FormView
,
UpdateView
from
django.urls
import
reverse_lazy
from
django.views.generic
import
TemplateView
,
ListView
from
django.views.generic.edit
import
CreateView
,
DeleteView
,
UpdateView
from
django.contrib.messages.views
import
SuccessMessageMixin
from
django.views.generic.detail
import
DetailView
,
SingleObjectMixin
from
common.const
import
create_success_msg
,
update_success_msg
from
..
import
forms
from
..models
import
A
sset
,
AssetGroup
,
AdminUser
,
Cluster
,
SystemUs
er
from
..models
import
A
dminUser
,
Clust
er
from
..hands
import
AdminUserRequiredMixin
__all__
=
[
'AdminUserCreateView'
,
'AdminUserDetailView'
,
'AdminUserDeleteView'
,
'AdminUserListView'
,
'AdminUserUpdateView'
,
'AdminUserAssetsView'
,
]
__all__
=
[
'AdminUserCreateView'
,
'AdminUserDetailView'
,
'AdminUserDeleteView'
,
'AdminUserListView'
,
'AdminUserUpdateView'
,
'AdminUserAssetsView'
,
]
class
AdminUserListView
(
AdminUserRequiredMixin
,
TemplateView
):
...
...
@@ -38,6 +40,7 @@ class AdminUserCreateView(AdminUserRequiredMixin,
form_class
=
forms
.
AdminUserForm
template_name
=
'assets/admin_user_create_update.html'
success_url
=
reverse_lazy
(
'assets:admin-user-list'
)
success_message
=
create_success_msg
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
...
...
@@ -47,20 +50,13 @@ class AdminUserCreateView(AdminUserRequiredMixin,
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
def
get_success_message
(
self
,
cleaned_data
):
success_message
=
_
(
'Create admin user <a href="{url}">{name}</a> successfully.'
.
format
(
url
=
reverse_lazy
(
'assets:admin-user-detail'
,
kwargs
=
{
'pk'
:
self
.
object
.
pk
}),
name
=
self
.
object
.
name
,
))
return
success_message
class
AdminUserUpdateView
(
AdminUserRequiredMixin
,
UpdateView
):
class
AdminUserUpdateView
(
AdminUserRequiredMixin
,
SuccessMessageMixin
,
UpdateView
):
model
=
AdminUser
form_class
=
forms
.
AdminUserForm
template_name
=
'assets/admin_user_create_update.html'
success_url
=
reverse_lazy
(
'assets:admin-user-list'
)
success_message
=
update_success_msg
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
...
...
@@ -70,11 +66,6 @@ class AdminUserUpdateView(AdminUserRequiredMixin, UpdateView):
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
def
get_success_url
(
self
):
success_url
=
reverse_lazy
(
'assets:admin-user-detail'
,
kwargs
=
{
'pk'
:
self
.
object
.
pk
})
return
success_url
class
AdminUserDetailView
(
AdminUserRequiredMixin
,
DetailView
):
model
=
AdminUser
...
...
This diff is collapsed.
Click to expand it.
apps/assets/views/asset.py
View file @
7f3d32a8
...
...
@@ -21,10 +21,11 @@ from django.core.cache import cache
from
django.utils
import
timezone
from
django.contrib.auth.mixins
import
LoginRequiredMixin
from
django.shortcuts
import
redirect
from
django.contrib.messages.views
import
SuccessMessageMixin
from
common.mixins
import
JSONResponseMixin
from
common.utils
import
get_object_or_none
,
get_logger
,
is_uuid
from
common.const
import
create_success_msg
,
update_success_msg
from
..
import
forms
from
..models
import
Asset
,
AssetGroup
,
AdminUser
,
Cluster
,
SystemUser
from
..hands
import
AdminUserRequiredMixin
...
...
@@ -46,7 +47,6 @@ class AssetListView(AdminUserRequiredMixin, TemplateView):
context
=
{
'app'
:
_
(
'Assets'
),
'action'
:
_
(
'Asset list'
),
# 'groups': AssetGroup.objects.all(),
'system_users'
:
SystemUser
.
objects
.
all
(),
}
kwargs
.
update
(
context
)
...
...
@@ -66,7 +66,7 @@ class UserAssetListView(LoginRequiredMixin, TemplateView):
return
super
()
.
get_context_data
(
**
kwargs
)
class
AssetCreateView
(
AdminUserRequiredMixin
,
CreateView
):
class
AssetCreateView
(
AdminUserRequiredMixin
,
SuccessMessageMixin
,
CreateView
):
model
=
Asset
form_class
=
forms
.
AssetCreateForm
template_name
=
'assets/asset_create.html'
...
...
@@ -87,6 +87,9 @@ class AssetCreateView(AdminUserRequiredMixin, CreateView):
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
def
get_success_message
(
self
,
cleaned_data
):
return
create_success_msg
%
({
"name"
:
cleaned_data
[
"hostname"
]})
class
AssetModalListView
(
AdminUserRequiredMixin
,
ListView
):
paginate_by
=
settings
.
CONFIG
.
DISPLAY_PER_PAGE
...
...
@@ -147,7 +150,7 @@ class AssetBulkUpdateView(AdminUserRequiredMixin, ListView):
return
super
()
.
get_context_data
(
**
kwargs
)
class
AssetUpdateView
(
AdminUserRequiredMixin
,
UpdateView
):
class
AssetUpdateView
(
AdminUserRequiredMixin
,
SuccessMessageMixin
,
UpdateView
):
model
=
Asset
form_class
=
forms
.
AssetUpdateForm
template_name
=
'assets/asset_update.html'
...
...
@@ -159,7 +162,10 @@ class AssetUpdateView(AdminUserRequiredMixin, UpdateView):
'action'
:
_
(
'Update asset'
),
}
kwargs
.
update
(
context
)
return
super
(
AssetUpdateView
,
self
)
.
get_context_data
(
**
kwargs
)
return
super
()
.
get_context_data
(
**
kwargs
)
def
get_success_message
(
self
,
cleaned_data
):
return
update_success_msg
%
({
"name"
:
cleaned_data
[
"hostname"
]})
class
AssetDeleteView
(
AdminUserRequiredMixin
,
DeleteView
):
...
...
@@ -184,14 +190,14 @@ class AssetDetailView(DetailView):
'system_users_all'
:
SystemUser
.
objects
.
all
(),
}
kwargs
.
update
(
context
)
return
super
(
AssetDetailView
,
self
)
.
get_context_data
(
**
kwargs
)
return
super
()
.
get_context_data
(
**
kwargs
)
@method_decorator
(
csrf_exempt
,
name
=
'dispatch'
)
class
AssetExportView
(
View
):
def
get
(
self
,
request
):
spm
=
request
.
GET
.
get
(
'spm'
,
''
)
assets_id_default
=
[
Asset
.
objects
.
first
()
.
id
]
if
Asset
.
objects
.
first
()
else
[
1
]
assets_id_default
=
[
Asset
.
objects
.
first
()
.
id
]
if
Asset
.
objects
.
first
()
else
[]
assets_id
=
cache
.
get
(
spm
,
assets_id_default
)
fields
=
[
field
for
field
in
Asset
.
_meta
.
fields
...
...
This diff is collapsed.
Click to expand it.
apps/assets/views/cluster.py
View file @
7f3d32a8
# coding:utf-8
from
__future__
import
absolute_import
,
unicode_literals
from
django.utils.translation
import
ugettext
as
_
from
django.views.generic
import
TemplateView
,
ListView
,
View
from
django.views.generic.edit
import
CreateView
,
DeleteView
,
FormView
,
UpdateView
from
django.urls
import
reverse_lazy
from
django.views.generic.detail
import
DetailView
,
SingleObjectMixin
from
django.contrib.messages.views
import
SuccessMessageMixin
from
common.const
import
create_success_msg
,
update_success_msg
from
..
import
forms
from
..models
import
Asset
,
AssetGroup
,
AdminUser
,
Cluster
,
SystemUser
from
..hands
import
AdminUserRequiredMixin
__all__
=
[
'ClusterListView'
,
'ClusterCreateView'
,
'ClusterUpdateView'
,
'ClusterDetailView'
,
'ClusterDeleteView'
,
'ClusterAssetsView'
]
__all__
=
[
'ClusterListView'
,
'ClusterCreateView'
,
'ClusterUpdateView'
,
'ClusterDetailView'
,
'ClusterDeleteView'
,
'ClusterAssetsView'
,
]
class
ClusterListView
(
AdminUserRequiredMixin
,
TemplateView
):
...
...
@@ -21,39 +25,40 @@ class ClusterListView(AdminUserRequiredMixin, TemplateView):
context
=
{
'app'
:
_
(
'Assets'
),
'action'
:
_
(
'Cluster list'
),
# 'keyword': self.request.GET.get('keyword', '')
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
class
ClusterCreateView
(
AdminUserRequiredMixin
,
CreateView
):
class
ClusterCreateView
(
AdminUserRequiredMixin
,
SuccessMessageMixin
,
CreateView
):
model
=
Cluster
form_class
=
forms
.
ClusterForm
template_name
=
'assets/cluster_create_update.html'
success_url
=
reverse_lazy
(
'assets:cluster-list'
)
success_message
=
create_success_msg
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
_
(
'assets'
),
'action'
:
_
(
'Create
C
luster'
),
'action'
:
_
(
'Create
c
luster'
),
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
def
form_valid
(
self
,
form
):
cluster
=
form
.
save
(
commit
=
False
)
cluster
.
created_by
=
self
.
request
.
user
.
username
or
'System'
cluster
.
created_by
=
self
.
request
.
user
.
username
cluster
.
save
()
return
super
()
.
form_valid
(
form
)
class
ClusterUpdateView
(
AdminUserRequiredMixin
,
UpdateView
):
class
ClusterUpdateView
(
AdminUserRequiredMixin
,
SuccessMessageMixin
,
UpdateView
):
model
=
Cluster
form_class
=
forms
.
ClusterForm
template_name
=
'assets/cluster_create_update.html'
context_object_name
=
'cluster'
success_url
=
reverse_lazy
(
'assets:cluster-list'
)
success_message
=
update_success_msg
def
form_valid
(
self
,
form
):
cluster
=
form
.
save
(
commit
=
False
)
...
...
This diff is collapsed.
Click to expand it.
apps/assets/views/group.py
View file @
7f3d32a8
...
...
@@ -7,42 +7,41 @@ from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateVi
from
django.urls
import
reverse_lazy
from
django.views.generic.detail
import
DetailView
,
SingleObjectMixin
from
django.shortcuts
import
get_object_or_404
,
reverse
,
redirect
from
django.contrib.messages.views
import
SuccessMessageMixin
from
common.const
import
create_success_msg
,
update_success_msg
from
..
import
forms
from
..models
import
Asset
,
AssetGroup
,
AdminUser
,
Cluster
,
SystemUser
from
..hands
import
AdminUserRequiredMixin
__all__
=
[
'AssetGroupCreateView'
,
'AssetGroupDetailView'
,
'AssetGroupUpdateView'
,
'AssetGroupListView'
,
'AssetGroupDeleteView'
,
]
__all__
=
[
'AssetGroupCreateView'
,
'AssetGroupDetailView'
,
'AssetGroupUpdateView'
,
'AssetGroupListView'
,
'AssetGroupDeleteView'
,
]
class
AssetGroupCreateView
(
AdminUserRequiredMixin
,
CreateView
):
class
AssetGroupCreateView
(
AdminUserRequiredMixin
,
SuccessMessageMixin
,
CreateView
):
model
=
AssetGroup
form_class
=
forms
.
AssetGroupForm
template_name
=
'assets/asset_group_create.html'
success_url
=
reverse_lazy
(
'assets:asset-group-list'
)
success_message
=
create_success_msg
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
_
(
'Assets'
),
'action'
:
_
(
'Create asset group'
),
'assets_count'
:
0
,
}
kwargs
.
update
(
context
)
return
super
(
AssetGroupCreateView
,
self
)
.
get_context_data
(
**
kwargs
)
return
super
()
.
get_context_data
(
**
kwargs
)
def
form_valid
(
self
,
form
):
asset_group
=
form
.
save
()
assets_id_list
=
self
.
request
.
POST
.
getlist
(
'assets'
,
[])
assets
=
[
get_object_or_404
(
Asset
,
id
=
int
(
asset_id
))
for
asset_id
in
assets_id_list
]
asset_group
.
created_by
=
self
.
request
.
user
.
username
or
'Admin'
asset_group
.
assets
.
add
(
*
tuple
(
assets
))
asset_group
.
save
()
return
super
(
AssetGroupCreateView
,
self
)
.
form_valid
(
form
)
group
=
form
.
save
()
group
.
created_by
=
self
.
request
.
user
.
username
group
.
save
()
return
super
()
.
form_valid
(
form
)
class
AssetGroupListView
(
AdminUserRequiredMixin
,
TemplateView
):
...
...
@@ -54,7 +53,6 @@ class AssetGroupListView(AdminUserRequiredMixin, TemplateView):
'action'
:
_
(
'Asset group list'
),
'assets'
:
Asset
.
objects
.
all
(),
'system_users'
:
SystemUser
.
objects
.
all
(),
'keyword'
:
self
.
request
.
GET
.
get
(
'keyword'
,
''
)
}
kwargs
.
update
(
context
)
return
super
(
AssetGroupListView
,
self
)
.
get_context_data
(
**
kwargs
)
...
...
@@ -77,27 +75,20 @@ class AssetGroupDetailView(AdminUserRequiredMixin, DetailView):
return
super
()
.
get_context_data
(
**
kwargs
)
class
AssetGroupUpdateView
(
AdminUserRequiredMixin
,
UpdateView
):
class
AssetGroupUpdateView
(
AdminUserRequiredMixin
,
SuccessMessageMixin
,
UpdateView
):
model
=
AssetGroup
form_class
=
forms
.
AssetGroupForm
template_name
=
'assets/asset_group_create.html'
success_url
=
reverse_lazy
(
'assets:asset-group-list'
)
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
self
.
object
=
self
.
get_object
(
queryset
=
AssetGroup
.
objects
.
all
())
return
super
(
AssetGroupUpdateView
,
self
)
.
get
(
request
,
*
args
,
**
kwargs
)
success_message
=
update_success_msg
def
get_context_data
(
self
,
**
kwargs
):
assets_all
=
self
.
object
.
assets
.
all
()
context
=
{
'app'
:
_
(
'Assets'
),
'action'
:
_
(
'Create asset group'
),
'assets_on_list'
:
assets_all
,
'assets_count'
:
len
(
assets_all
),
'group_id'
:
self
.
object
.
id
,
}
kwargs
.
update
(
context
)
return
super
(
AssetGroupUpdateView
,
self
)
.
get_context_data
(
**
kwargs
)
return
super
()
.
get_context_data
(
**
kwargs
)
class
AssetGroupDeleteView
(
AdminUserRequiredMixin
,
DeleteView
):
...
...
This diff is collapsed.
Click to expand it.
apps/assets/views/system_user.py
View file @
7f3d32a8
# ~*~ coding: utf-8 ~*~
from
django.contrib
import
messages
from
django.shortcuts
import
redirect
,
reverse
from
django.utils.translation
import
ugettext
as
_
from
django.db
import
transaction
from
django.views.generic
import
TemplateView
,
ListView
,
FormView
from
django.views.generic
import
TemplateView
from
django.views.generic.edit
import
CreateView
,
DeleteView
,
UpdateView
from
django.urls
import
reverse_lazy
from
django.contrib.messages.views
import
SuccessMessageMixin
from
django.views.generic.detail
import
DetailView
,
SingleObjectMixin
from
django.views.generic.detail
import
DetailView
from
..forms
import
SystemUserForm
,
SystemUserUpdateForm
,
SystemUserAuthForm
from
common.const
import
create_success_msg
,
update_success_msg
from
..forms
import
SystemUserForm
,
SystemUserUpdateForm
from
..models
import
SystemUser
,
Cluster
from
..hands
import
AdminUserRequiredMixin
__all__
=
[
'SystemUserCreateView'
,
'SystemUserUpdateView'
,
'SystemUserDetailView'
,
'SystemUserDeleteView'
,
'SystemUserAssetView'
,
'SystemUserListView'
,
]
__all__
=
[
'SystemUserCreateView'
,
'SystemUserUpdateView'
,
'SystemUserDetailView'
,
'SystemUserDeleteView'
,
'SystemUserAssetView'
,
'SystemUserListView'
,
]
class
SystemUserListView
(
AdminUserRequiredMixin
,
TemplateView
):
...
...
@@ -38,10 +37,7 @@ class SystemUserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateVi
form_class
=
SystemUserForm
template_name
=
'assets/system_user_create.html'
success_url
=
reverse_lazy
(
'assets:system-user-list'
)
@transaction.atomic
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
return
super
(
SystemUserCreateView
,
self
)
.
post
(
request
,
*
args
,
**
kwargs
)
success_message
=
create_success_msg
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
...
...
@@ -51,20 +47,13 @@ class SystemUserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateVi
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
def
get_success_message
(
self
,
cleaned_data
):
url
=
reverse
(
'assets:system-user-detail'
,
kwargs
=
{
'pk'
:
self
.
object
.
pk
})
success_message
=
_
(
'Create system user <a href="{url}">{name}</a> '
'successfully.'
.
format
(
url
=
url
,
name
=
self
.
object
.
name
)
)
return
success_message
class
SystemUserUpdateView
(
AdminUserRequiredMixin
,
UpdateView
):
class
SystemUserUpdateView
(
AdminUserRequiredMixin
,
SuccessMessageMixin
,
UpdateView
):
model
=
SystemUser
form_class
=
SystemUserUpdateForm
template_name
=
'assets/system_user_update.html'
success_url
=
reverse_lazy
(
'assets:system-user-list'
)
success_message
=
update_success_msg
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
...
...
@@ -74,11 +63,6 @@ class SystemUserUpdateView(AdminUserRequiredMixin, UpdateView):
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
def
get_success_url
(
self
):
success_url
=
reverse_lazy
(
'assets:system-user-detail'
,
kwargs
=
{
'pk'
:
self
.
object
.
pk
})
return
success_url
class
SystemUserDetailView
(
AdminUserRequiredMixin
,
DetailView
):
template_name
=
'assets/system_user_detail.html'
...
...
@@ -109,8 +93,8 @@ class SystemUserAssetView(AdminUserRequiredMixin, DetailView):
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
'assets'
,
'action'
:
'System user asset'
,
'app'
:
_
(
'assets'
)
,
'action'
:
_
(
'System user asset'
)
,
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
This diff is collapsed.
Click to expand it.
apps/common/const.py
0 → 100644
View file @
7f3d32a8
# -*- coding: utf-8 -*-
#
from
django.utils.translation
import
ugettext
as
_
create_success_msg
=
_
(
"<b>
%(name)
s</b> was created successfully"
)
update_success_msg
=
_
(
"<b>
%(name)
s</b> was updated successfully"
)
\ No newline at end of file
This diff is collapsed.
Click to expand it.
apps/common/utils.py
View file @
7f3d32a8
...
...
@@ -287,10 +287,10 @@ def make_signature(access_key_secret, date=None):
return
content_md5
(
data
)
def
encrypt_password
(
password
):
def
encrypt_password
(
password
,
salt
=
None
):
from
passlib.hash
import
sha512_crypt
if
password
:
return
sha512_crypt
.
using
(
rounds
=
5000
)
.
hash
(
password
)
return
sha512_crypt
.
using
(
rounds
=
5000
)
.
hash
(
password
,
salt
=
salt
)
return
None
...
...
This diff is collapsed.
Click to expand it.
apps/jumpserver/middleware.py
View file @
7f3d32a8
...
...
@@ -4,24 +4,44 @@ import os
import
re
import
pytz
from
django.utils
import
timezone
from
django.utils.deprecation
import
MiddlewareMixin
from
django.shortcuts
import
HttpResponse
DEMO_MODE
=
os
.
environ
.
get
(
"DEMO_MODE"
,
""
)
SAFE_URL
=
r'^/users/login|^/api/terminal/v1/.*|/api/terminal/.*|/api/users/v1/auth/|/api/users/v1/profile/'
class
TimezoneMiddleware
:
def
__init__
(
self
,
get_response
):
self
.
get_response
=
get_response
class
TimezoneMiddleware
(
MiddlewareMixin
):
def
process_request
(
self
,
request
):
def
__call__
(
self
,
request
):
tzname
=
request
.
META
.
get
(
'TZ'
)
if
tzname
:
timezone
.
activate
(
pytz
.
timezone
(
tzname
))
else
:
timezone
.
deactivate
()
response
=
self
.
get_response
(
request
)
return
response
class
DemoMiddleware
:
DEMO_MODE_ENABLED
=
os
.
environ
.
get
(
"DEMO_MODE"
,
""
)
in
(
"1"
,
"ok"
,
"True"
)
SAFE_URL_PATTERN
=
re
.
compile
(
r'^/users/login|'
r'^/api/terminal/v1/.*|'
r'^/api/terminal/.*|'
r'^/api/users/v1/auth/|'
r'^/api/users/v1/profile/'
)
SAFE_METHOD
=
(
"GET"
,
"HEAD"
)
def
__init__
(
self
,
get_response
):
self
.
get_response
=
get_response
class
DemoMiddleware
(
MiddlewareMixin
):
def
process_request
(
self
,
request
):
if
DEMO_MODE
and
request
.
method
not
in
[
"GET"
,
"HEAD"
]
and
not
re
.
match
(
SAFE_URL
,
request
.
path
):
return
HttpResponse
(
"Demo mode, only get request accept"
,
status
=
403
)
if
self
.
DEMO_MODE_ENABLED
:
print
(
"Demo mode enabled, reject unsafe method and url"
)
def
__call__
(
self
,
request
):
if
self
.
DEMO_MODE_ENABLED
and
request
.
method
not
in
self
.
SAFE_METHOD
\
and
not
self
.
SAFE_URL_PATTERN
.
match
(
request
.
path
):
return
HttpResponse
(
"Demo mode, only safe request accepted"
,
status
=
403
)
else
:
response
=
self
.
get_response
(
request
)
return
response
This diff is collapsed.
Click to expand it.
apps/jumpserver/settings.py
View file @
7f3d32a8
...
...
@@ -240,9 +240,8 @@ LOGGING = {
# Internationalization
# https://docs.djangoproject.com/en/1.10/topics/i18n/
LANGUAGE_CODE
=
'
en-us
'
LANGUAGE_CODE
=
'
zh-cn
'
# TIME_ZONE = 'UTC'
TIME_ZONE
=
'Asia/Shanghai'
USE_I18N
=
True
...
...
@@ -300,7 +299,8 @@ REST_FRAMEWORK = {
'users.authentication.SessionAuthentication'
,
),
'DEFAULT_FILTER_BACKENDS'
:
(
'django_filters.rest_framework.DjangoFilterBackend'
,),
'DATETIME_FORMAT'
:
'
%
Y-
%
m-
%
d
%
H:
%
M:
%
S'
,
'DATETIME_FORMAT'
:
'
%
Y-
%
m-
%
d
%
H:
%
M:
%
S
%
z'
,
'DATETIME_INPUT_FORMATS'
:
[
'
%
Y-
%
m-
%
d
%
H:
%
M:
%
S
%
z'
],
}
AUTHENTICATION_BACKENDS
=
[
...
...
@@ -374,4 +374,5 @@ BOOTSTRAP3 = {
'horizontal_field_class'
:
'col-md-9'
,
# Set placeholder attributes to label if no placeholder is provided
'set_placeholder'
:
True
,
'success_css_class'
:
''
,
}
This diff is collapsed.
Click to expand it.
apps/jumpserver/urls.py
View file @
7f3d32a8
...
...
@@ -36,6 +36,6 @@ urlpatterns = [
if
settings
.
DEBUG
:
urlpatterns
+=
[
url
(
r'^docs/'
,
schema_view
,
name
=
"docs"
),
]
+
static
(
settings
.
STATIC_URL
,
document_root
=
settings
.
STATIC_
DIR
)
\
]
+
static
(
settings
.
STATIC_URL
,
document_root
=
settings
.
STATIC_
ROOT
)
\
+
static
(
settings
.
MEDIA_URL
,
document_root
=
settings
.
MEDIA_ROOT
)
This diff is collapsed.
Click to expand it.
apps/locale/zh/LC_MESSAGES/django.mo
View file @
7f3d32a8
No preview for this file type
This diff is collapsed.
Click to expand it.
apps/locale/zh/LC_MESSAGES/django.po
View file @
7f3d32a8
This diff is collapsed.
Click to expand it.
apps/ops/api.py
View file @
7f3d32a8
...
...
@@ -2,11 +2,13 @@
from
django.shortcuts
import
get_object_or_404
from
rest_framework
import
viewsets
from
rest_framework
import
viewsets
,
generics
from
rest_framework.views
import
Response
from
.hands
import
IsSuperUser
from
.models
import
Task
,
AdHoc
,
AdHocRunHistory
from
.serializers
import
TaskSerializer
,
AdHocSerializer
,
AdHocRunHistorySerializer
from
.tasks
import
run_ansible_task
class
TaskViewSet
(
viewsets
.
ModelViewSet
):
...
...
@@ -15,6 +17,17 @@ class TaskViewSet(viewsets.ModelViewSet):
permission_classes
=
(
IsSuperUser
,)
class
TaskRun
(
generics
.
RetrieveAPIView
):
queryset
=
Task
.
objects
.
all
()
serializer_class
=
TaskViewSet
permission_classes
=
(
IsSuperUser
,)
def
retrieve
(
self
,
request
,
*
args
,
**
kwargs
):
task
=
self
.
get_object
()
run_ansible_task
.
delay
(
str
(
task
.
id
))
return
Response
({
"msg"
:
"start"
})
class
AdHocViewSet
(
viewsets
.
ModelViewSet
):
queryset
=
AdHoc
.
objects
.
all
()
serializer_class
=
AdHocSerializer
...
...
This diff is collapsed.
Click to expand it.
apps/ops/hands.py
View file @
7f3d32a8
# ~*~ coding: utf-8 ~*~
from
users.permissions
import
IsSuperUser
from
users.utils
import
AdminUserRequiredMixin
\ No newline at end of file
This diff is collapsed.
Click to expand it.
apps/ops/models.py
View file @
7f3d32a8
...
...
@@ -235,6 +235,7 @@ class AdHoc(models.Model):
return
result
.
results_raw
,
result
.
results_summary
except
AnsibleError
as
e
:
logger
.
error
(
"Failed run adhoc {}, {}"
.
format
(
self
.
task
.
name
,
e
))
pass
@become.setter
def
become
(
self
,
item
):
...
...
This diff is collapsed.
Click to expand it.
apps/ops/templates/ops/adhoc_detail.html
View file @
7f3d32a8
...
...
@@ -3,9 +3,9 @@
{% load i18n %}
{% block custom_head_css_js %}
<link
href=
"{% static
"
css
/
plugins
/
select2
/
select2
.
min
.
css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static
'css/plugins/select2/select2.min.css'
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
plugins
/
sweetalert
/
sweetalert
.
css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static
"
js
/
plugins
/
select2
/
select2
.
full
.
min
.
js
"
%}"
></script>
<script
src=
"{% static
'js/plugins/select2/select2.full.min.js'
%}"
></script>
<script
src=
"{% static "
js
/
plugins
/
sweetalert
/
sweetalert
.
min
.
js
"
%}"
></script>
{% endblock %}
{% block content %}
...
...
This diff is collapsed.
Click to expand it.
apps/ops/templates/ops/adhoc_history.html
View file @
7f3d32a8
...
...
@@ -3,9 +3,9 @@
{% load i18n %}
{% block custom_head_css_js %}
<link
href=
"{% static
"
css
/
plugins
/
select2
/
select2
.
min
.
css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static
'css/plugins/select2/select2.min.css'
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
plugins
/
sweetalert
/
sweetalert
.
css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static
"
js
/
plugins
/
select2
/
select2
.
full
.
min
.
js
"
%}"
></script>
<script
src=
"{% static
'js/plugins/select2/select2.full.min.js'
%}"
></script>
<script
src=
"{% static "
js
/
plugins
/
sweetalert
/
sweetalert
.
min
.
js
"
%}"
></script>
{% endblock %}
{% block content %}
...
...
This diff is collapsed.
Click to expand it.
apps/ops/templates/ops/adhoc_history_detail.html
View file @
7f3d32a8
...
...
@@ -3,9 +3,9 @@
{% load i18n %}
{% block custom_head_css_js %}
<link
href=
"{% static
"
css
/
plugins
/
select2
/
select2
.
min
.
css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static
'css/plugins/select2/select2.min.css'
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
plugins
/
sweetalert
/
sweetalert
.
css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static
"
js
/
plugins
/
select2
/
select2
.
full
.
min
.
js
"
%}"
></script>
<script
src=
"{% static
'js/plugins/select2/select2.full.min.js'
%}"
></script>
<script
src=
"{% static "
js
/
plugins
/
sweetalert
/
sweetalert
.
min
.
js
"
%}"
></script>
{% endblock %}
{% block content %}
...
...
This diff is collapsed.
Click to expand it.
apps/ops/templates/ops/task_adhoc.html
View file @
7f3d32a8
...
...
@@ -3,9 +3,9 @@
{% load i18n %}
{% block custom_head_css_js %}
<link
href=
"{% static
"
css
/
plugins
/
select2
/
select2
.
min
.
css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static
'css/plugins/select2/select2.min.css'
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
plugins
/
sweetalert
/
sweetalert
.
css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static
"
js
/
plugins
/
select2
/
select2
.
full
.
min
.
js
"
%}"
></script>
<script
src=
"{% static
'js/plugins/select2/select2.full.min.js'
%}"
></script>
<script
src=
"{% static "
js
/
plugins
/
sweetalert
/
sweetalert
.
min
.
js
"
%}"
></script>
{% endblock %}
{% block content %}
...
...
This diff is collapsed.
Click to expand it.
apps/ops/templates/ops/task_detail.html
View file @
7f3d32a8
...
...
@@ -3,9 +3,9 @@
{% load i18n %}
{% block custom_head_css_js %}
<link
href=
"{% static
"
css
/
plugins
/
select2
/
select2
.
min
.
css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static
'css/plugins/select2/select2.min.css'
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
plugins
/
sweetalert
/
sweetalert
.
css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static
"
js
/
plugins
/
select2
/
select2
.
full
.
min
.
js
"
%}"
></script>
<script
src=
"{% static
'js/plugins/select2/select2.full.min.js'
%}"
></script>
<script
src=
"{% static "
js
/
plugins
/
sweetalert
/
sweetalert
.
min
.
js
"
%}"
></script>
{% endblock %}
{% block content %}
...
...
@@ -89,7 +89,7 @@
<td>
<b>
{% for task in object.latest_adhoc.tasks %}
{{ forloop.counter }}. {{ task.name }} : {{ task.action.module }}
<br/>
{{ forloop.counter }}. {{ task.name }} :
::
{{ task.action.module }}
<br/>
{% endfor %}
</b>
</td>
...
...
This diff is collapsed.
Click to expand it.
apps/ops/templates/ops/task_history.html
View file @
7f3d32a8
...
...
@@ -3,9 +3,9 @@
{% load i18n %}
{% block custom_head_css_js %}
<link
href=
"{% static
"
css
/
plugins
/
select2
/
select2
.
min
.
css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static
'css/plugins/select2/select2.min.css'
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
plugins
/
sweetalert
/
sweetalert
.
css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static
"
js
/
plugins
/
select2
/
select2
.
full
.
min
.
js
"
%}"
></script>
<script
src=
"{% static
'js/plugins/select2/select2.full.min.js'
%}"
></script>
<script
src=
"{% static "
js
/
plugins
/
sweetalert
/
sweetalert
.
min
.
js
"
%}"
></script>
{% endblock %}
{% block content %}
...
...
This diff is collapsed.
Click to expand it.
apps/ops/templates/ops/task_list.html
View file @
7f3d32a8
...
...
@@ -67,6 +67,7 @@
{% endif %}
</td>
<td
class=
"text-center"
>
<a
data-uid=
"{{ object.id }}"
class=
"btn btn-xs btn-primary btn-run"
>
{% trans "Run" %}
</a>
<a
data-uid=
"{{ object.id }}"
class=
"btn btn-xs btn-danger btn-del"
>
{% trans "Delete" %}
</a>
</td>
</tr>
...
...
@@ -98,10 +99,32 @@ $(document).ready(function() {
}).
on
(
'click'
,
'.btn-del'
,
function
()
{
var
$this
=
$
(
this
);
var
name
=
$
(
this
)
.
closest
(
"tr"
).
find
(
":nth-child(2)"
).
children
(
'a'
).
html
();
var
name
=
$
this
.
closest
(
"tr"
).
find
(
":nth-child(2)"
).
children
(
'a'
).
html
();
var
uid
=
$this
.
data
(
'uid'
);
var
the_url
=
'{% url "api-ops:task-detail" pk=DEFAULT_PK %}'
.
replace
(
'{{ DEFAULT_PK }}'
,
uid
);
objectDelete
(
$this
,
name
,
the_url
);
}).
on
(
'click'
,
'.btn-run'
,
function
()
{
var
$this
=
$
(
this
);
var
name
=
$this
.
closest
(
"tr"
).
find
(
":nth-child(2)"
).
children
(
'a'
).
html
();
var
uid
=
$this
.
data
(
'uid'
);
var
the_url
=
'{% url "api-ops:task-run" pk=DEFAULT_PK %}'
.
replace
(
'{{ DEFAULT_PK }}'
,
uid
);
var
error
=
function
(
data
)
{
alert
(
data
)
};
var
success
=
function
()
{
setTimeout
(
function
()
{
console
.
log
(
"ok"
)
},
1000
);
window
.
location
=
"{% url 'ops:task-detail' pk=DEFAULT_PK %}"
.
replace
(
'{{ DEFAULT_PK }}'
,
uid
);
};
APIUpdateAttr
({
url
:
the_url
,
error
:
error
,
method
:
'GET'
,
success
:
success
,
success_message
:
"{% trans 'Task start: ' %}"
+
" "
+
name
});
})
</script>
{% endblock %}
...
...
This diff is collapsed.
Click to expand it.
apps/ops/urls/api_urls.py
View file @
7f3d32a8
# ~*~ coding: utf-8 ~*~
from
__future__
import
unicode_literals
from
django.conf.urls
import
url
from
rest_framework.routers
import
DefaultRouter
from
..
import
api
...
...
@@ -12,6 +13,8 @@ router.register(r'v1/tasks', api.TaskViewSet, 'task')
router
.
register
(
r'v1/adhoc'
,
api
.
AdHocViewSet
,
'adhoc'
)
router
.
register
(
r'v1/history'
,
api
.
AdHocRunHistorySet
,
'history'
)
urlpatterns
=
[]
urlpatterns
=
[
url
(
r'^v1/tasks/(?P<pk>[0-9a-zA-Z\-]{36})/run/$'
,
api
.
TaskRun
.
as_view
(),
name
=
'task-run'
),
]
urlpatterns
+=
router
.
urls
This diff is collapsed.
Click to expand it.
apps/ops/views.py
View file @
7f3d32a8
...
...
@@ -6,9 +6,10 @@ from django.views.generic import ListView, DetailView
from
common.mixins
import
DatetimeSearchMixin
from
.models
import
Task
,
AdHoc
,
AdHocRunHistory
from
.hands
import
AdminUserRequiredMixin
class
TaskListView
(
DatetimeSearchMixin
,
ListView
):
class
TaskListView
(
AdminUserRequiredMixin
,
DatetimeSearchMixin
,
ListView
):
paginate_by
=
settings
.
CONFIG
.
DISPLAY_PER_PAGE
model
=
Task
ordering
=
(
'-date_created'
,)
...
...
@@ -42,7 +43,7 @@ class TaskListView(DatetimeSearchMixin, ListView):
return
super
()
.
get_context_data
(
**
kwargs
)
class
TaskDetailView
(
DetailView
):
class
TaskDetailView
(
AdminUserRequiredMixin
,
DetailView
):
model
=
Task
template_name
=
'ops/task_detail.html'
...
...
@@ -55,7 +56,7 @@ class TaskDetailView(DetailView):
return
super
()
.
get_context_data
(
**
kwargs
)
class
TaskAdhocView
(
DetailView
):
class
TaskAdhocView
(
AdminUserRequiredMixin
,
DetailView
):
model
=
Task
template_name
=
'ops/task_adhoc.html'
...
...
@@ -68,7 +69,7 @@ class TaskAdhocView(DetailView):
return
super
()
.
get_context_data
(
**
kwargs
)
class
TaskHistoryView
(
DetailView
):
class
TaskHistoryView
(
AdminUserRequiredMixin
,
DetailView
):
model
=
Task
template_name
=
'ops/task_history.html'
...
...
@@ -81,7 +82,7 @@ class TaskHistoryView(DetailView):
return
super
()
.
get_context_data
(
**
kwargs
)
class
AdHocDetailView
(
DetailView
):
class
AdHocDetailView
(
AdminUserRequiredMixin
,
DetailView
):
model
=
AdHoc
template_name
=
'ops/adhoc_detail.html'
...
...
@@ -94,7 +95,7 @@ class AdHocDetailView(DetailView):
return
super
()
.
get_context_data
(
**
kwargs
)
class
AdHocHistoryView
(
DetailView
):
class
AdHocHistoryView
(
AdminUserRequiredMixin
,
DetailView
):
model
=
AdHoc
template_name
=
'ops/adhoc_history.html'
...
...
@@ -107,7 +108,7 @@ class AdHocHistoryView(DetailView):
return
super
()
.
get_context_data
(
**
kwargs
)
class
AdHocHistoryDetailView
(
DetailView
):
class
AdHocHistoryDetailView
(
AdminUserRequiredMixin
,
DetailView
):
model
=
AdHocRunHistory
template_name
=
'ops/adhoc_history_detail.html'
...
...
This diff is collapsed.
Click to expand it.
apps/perms/forms.py
View file @
7f3d32a8
...
...
@@ -15,7 +15,8 @@ class AssetPermissionForm(forms.ModelForm):
widget
=
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select users'
)},
),
label
=
_
(
"User"
)
label
=
_
(
"User"
),
required
=
False
,
)
class
Meta
:
...
...
@@ -41,35 +42,54 @@ class AssetPermissionForm(forms.ModelForm):
help_texts
=
{
'name'
:
'* required'
,
'system_users'
:
'* required'
,
'user_groups'
:
_
(
'User or user group at least one required'
),
'asset_groups'
:
_
(
'Asset or Asset group at least one required'
),
}
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"
]
def
clean_system_users
(
self
):
from
assets.utils
import
check_assets_have_system_user
errors
=
[]
assets
=
self
.
cleaned_data
[
'assets'
]
asset_groups
=
self
.
cleaned_data
[
'asset_groups'
]
system_users
=
self
.
cleaned_data
[
'system_users'
]
asset_groups
=
self
.
cleaned_data
.
get
(
'asset_groups'
)
system_users
=
self
.
cleaned_data
.
get
(
'system_users'
)
if
not
asset_groups
and
not
assets
:
return
self
.
cleaned_data
.
get
(
"system_users"
)
error_data
=
check_assets_have_system_user
(
assets
,
system_users
)
if
error_data
:
for
asset
,
system_users
in
error_data
.
items
():
msg
=
_
(
"Asset {} not have [{}] system users, please check
\n
"
)
msg
=
_
(
"Asset {}
of cluster {}
not have [{}] system users, please check
\n
"
)
error
=
forms
.
ValidationError
(
msg
.
format
(
asset
.
hostname
,
asset
.
cluster
.
name
,
", "
.
join
(
system_user
.
name
for
system_user
in
system_users
)
))
errors
.
append
(
error
)
for
group
in
asset_groups
:
msg
=
_
(
"Asset {}
: {} not have [{}] system users, please check
"
)
msg
=
_
(
"Asset {}
(group {}) of cluster {} not have [{}] system users, please check
\n
"
)
assets
=
group
.
assets
.
all
()
error_data
=
check_assets_have_system_user
(
assets
,
system_users
)
for
asset
,
system_users
in
error_data
.
items
():
errors
.
append
(
msg
.
format
(
group
.
name
,
asset
.
host
name
,
asset
.
hostname
,
group
.
name
,
asset
.
cluster
.
name
,
", "
.
join
(
system_user
.
name
for
system_user
in
system_users
)
))
if
errors
:
...
...
This diff is collapsed.
Click to expand it.
apps/perms/templates/perms/asset_permission_asset.html
View file @
7f3d32a8
...
...
@@ -3,8 +3,8 @@
{% 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>
<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"
>
...
...
@@ -53,8 +53,6 @@
<tr>
<th>
{% trans 'Hostname' %}
</th>
<th>
{% trans 'IP' %}
</th>
<th>
{% trans 'Port' %}
</th>
<th>
{% trans 'Is valid' %}
</th>
<th></th>
</tr>
</thead>
...
...
@@ -63,15 +61,6 @@
<tr>
<td>
{{ asset.hostname }}
</td>
<td>
{{ asset.ip }}
</td>
<td>
{{ user.port }}
</td>
<td>
{% if asset.is_active %}
<i
class=
"fa fa-times text-danger"
></i>
{% else %}
<i
class=
"fa fa-check text-navy"
></i>
{% endif %}
</td>
<td>
<button
title=
"{{ asset.inherit_from_asset_groups }}"
data-gid=
"{{ asset.id }}"
class=
"btn btn-danger btn-xs btn-remove-asset {% if asset.is_inherit_from_asset_groups %} disabled {% endif %}"
type=
"button"
style=
"float: right;"
><i
class=
"fa fa-minus"
></i></button>
</td>
...
...
This diff is collapsed.
Click to expand it.
apps/perms/templates/perms/asset_permission_detail.html
View file @
7f3d32a8
...
...
@@ -3,8 +3,8 @@
{% 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>
<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 %}
...
...
@@ -27,11 +27,11 @@
<i
class=
"fa fa-bar-chart-o"
></i>
{% trans 'Assets and asset groups' %}
</a>
</li>
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'perms:asset-permission-update' pk=asset_permission.id %}"
><i
class=
"fa fa-edit"
></i>
Update
</a>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'perms:asset-permission-update' pk=asset_permission.id %}"
><i
class=
"fa fa-edit"
></i>
{% trans 'Update' %}
</a>
</li>
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline btn-danger btn-delete-perm"
>
<i
class=
"fa fa-
edit"
></i>
Delete
<i
class=
"fa fa-
trash-o"
></i>
{% trans 'Delete' %}
</a>
</li>
</ul>
...
...
@@ -113,7 +113,7 @@
<table
class=
"table"
>
<tbody>
<tr
class=
"no-borders-tr"
>
<td
width=
"50%"
>
Active
:
</td>
<td
width=
"50%"
>
{% trans 'Active' %}
:
</td>
<td><span
style=
"float: right"
>
<div
class=
"switch"
>
<div
class=
"onoffswitch"
>
...
...
@@ -139,8 +139,8 @@
<table
class=
"table"
id=
"system-user-table"
>
<tbody>
<form>
<tr>
<td
colspan=
"2"
class=
"no-borders"
>
<tr
class=
"no-borders-tr"
>
<td
colspan=
"2"
>
<select
data-placeholder=
"{% trans 'Select system users' %}"
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.name }}
</option>
...
...
@@ -148,15 +148,15 @@
</select>
</td>
</tr>
<tr>
<td
colspan=
"2"
class=
"no-borders"
>
<tr
class=
"no-borders-tr"
>
<td
colspan=
"2"
>
<button
type=
"button"
class=
"btn btn-info btn-small"
id=
"btn-add-system-user"
>
{% trans 'Add' %}
</button>
</td>
</tr>
</form>
{% for system_user in system_users %}
<tr>
<tr
{%
if
forloop
.
counter =
=
1
%}
class=
"no-borders-tr"
{%
endif
%}
>
<td
><b
class=
"bdg-system-user"
data-uid=
{{
system_user
.
id
}}
>
{{ system_user.name }}
</b></td>
<td>
<button
class=
"btn btn-danger btn-xs btn-remove-user"
data-uid=
"{{ system_user.id }}"
type=
"button"
style=
"float: right;"
><i
class=
"fa fa-minus"
></i></button>
...
...
@@ -237,6 +237,16 @@ $(document).ready(function () {
}).
get
();
updateSystemUser
(
system_users
);
$tr
.
remove
()
}).
on
(
'click'
,
'#is_active'
,
function
()
{
var
the_url
=
'{% url "api-perms:asset-permission-detail" pk=asset_permission.id %}'
;
var
checked
=
$
(
this
).
prop
(
'checked'
);
var
body
=
{
'is_active'
:
checked
};
APIUpdateAttr
({
url
:
the_url
,
body
:
JSON
.
stringify
(
body
),
});
})
</script>
{% endblock %}
This diff is collapsed.
Click to expand it.
apps/perms/templates/perms/asset_permission_list.html
View file @
7f3d32a8
...
...
@@ -69,9 +69,11 @@ function initTable() {
$
(
td
).
html
(
'<i class="fa fa-check text-navy"></i>'
)
}
}},
{
targets
:
8
,
createdCell
:
function
(
td
,
cellData
)
{
{
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-permission" data-uid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
);
var
del_btn
=
'<a class="btn btn-xs btn-danger m-l-xs btn-del" data-uid="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Delete" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
)
.
replace
(
'99991938'
,
rowData
.
name
);
$
(
td
).
html
(
update_btn
+
del_btn
);
}}
...
...
This diff is collapsed.
Click to expand it.
apps/perms/templates/perms/asset_permission_user.html
View file @
7f3d32a8
...
...
@@ -3,8 +3,8 @@
{% 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>
<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"
>
...
...
@@ -53,8 +53,6 @@
<tr>
<th>
{% trans 'Name' %}
</th>
<th>
{% trans 'Username' %}
</th>
<th>
{% trans 'Email' %}
</th>
<th>
{% trans 'Is valid' %}
</th>
<th></th>
</tr>
</thead>
...
...
@@ -63,15 +61,6 @@
<tr>
<td>
{{ user.name }}
</td>
<td>
{{ user.username }}
</td>
<td>
{{ user.email }}
</td>
<td>
{% if user.is_expired and user.is_active %}
<i
class=
"fa fa-times text-danger"
></i>
{% else %}
<i
class=
"fa fa-check text-navy"
></i>
{% endif %}
</td>
<td>
<button
class=
"btn btn-danger btn-xs btn-remove-user {% if user.is_inherit_from_user_groups %} disabled {% endif %}"
data-gid=
"{{ user.id }}"
type=
"button"
style=
"float: right;"
><i
class=
"fa fa-minus"
></i></button>
</td>
...
...
@@ -231,7 +220,6 @@ $(document).ready(function () {
$
.
map
(
jumpserver
.
users_selected
,
function
(
value
,
index
)
{
users_id
.
push
(
index
);
});
console
.
log
(
users_id
);
addUsers
(
users_id
);
}).
on
(
'click'
,
'.btn-remove-user'
,
function
()
{
var
user_id
=
$
(
this
).
data
(
"gid"
);
...
...
This diff is collapsed.
Click to expand it.
apps/perms/urls/api_urls.py
View file @
7f3d32a8
...
...
@@ -7,9 +7,7 @@ from .. import api
app_name
=
'perms'
router
=
routers
.
DefaultRouter
()
router
.
register
(
'v1/asset-permissions'
,
api
.
AssetPermissionViewSet
,
'asset-permission'
)
router
.
register
(
'v1/asset-permissions'
,
api
.
AssetPermissionViewSet
,
'asset-permission'
)
urlpatterns
=
[
# 用户可以使用自己的Token或其它认证查看自己授权的资产,资产组等
...
...
This diff is collapsed.
Click to expand it.
apps/perms/views.py
View file @
7f3d32a8
...
...
@@ -11,6 +11,7 @@ from django.contrib.messages.views import SuccessMessageMixin
from
django.views.generic.detail
import
DetailView
,
SingleObjectMixin
from
django.contrib
import
messages
from
common.const
import
create_success_msg
,
update_success_msg
from
.hands
import
AdminUserRequiredMixin
,
User
,
UserGroup
,
SystemUser
,
\
Asset
,
AssetGroup
from
.models
import
AssetPermission
...
...
@@ -31,46 +32,12 @@ class AssetPermissionListView(AdminUserRequiredMixin, ListView):
return
super
()
.
get_context_data
(
**
kwargs
)
class
MessageMixin
:
def
form_valid
(
self
,
form
):
response
=
super
()
.
form_valid
(
form
)
errors
=
self
.
object
.
check_system_user_in_assets
()
if
errors
:
message
=
self
.
get_warning_messages
(
errors
)
messages
.
warning
(
self
.
request
,
message
)
else
:
message
=
self
.
get_success_message
(
form
.
cleaned_data
)
messages
.
success
(
self
.
request
,
message
)
success_message
=
self
.
get_success_message
(
form
.
cleaned_data
)
if
success_message
:
messages
.
success
(
self
.
request
,
success_message
)
return
response
@staticmethod
def
get_warning_messages
(
errors
):
message
=
"<b><i class='fa fa-warning'></i>WARNING: System user "
\
"should in behind clusters, so that "
\
"system user cat auto push to the cluster assets:</b> <br>"
for
system_user
,
clusters
in
errors
.
items
():
message
+=
" >>> {}: {} "
.
format
(
system_user
.
name
,
", "
.
join
((
cluster
.
name
for
cluster
in
clusters
)))
return
message
def
get_success_message
(
self
,
cleaned_data
):
url
=
reverse_lazy
(
'perms:asset-permission-detail'
,
kwargs
=
{
'pk'
:
self
.
object
.
pk
})
success_message
=
_
(
'Create asset permission <a href="{url}"> {name} </a> '
'successfully.'
.
format
(
url
=
url
,
name
=
self
.
object
.
name
))
return
success_message
class
AssetPermissionCreateView
(
AdminUserRequiredMixin
,
SuccessMessageMixin
,
CreateView
):
model
=
AssetPermission
form_class
=
AssetPermissionForm
template_name
=
'perms/asset_permission_create_update.html'
success_url
=
reverse_lazy
(
'perms:asset-permission-list'
)
warning
=
None
success_message
=
create_success_msg
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
...
...
@@ -80,23 +47,13 @@ class AssetPermissionCreateView(AdminUserRequiredMixin, SuccessMessageMixin, Cre
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
def
get_success_message
(
self
,
cleaned_data
):
url
=
reverse_lazy
(
'perms:asset-permission-detail'
,
kwargs
=
{
'pk'
:
self
.
object
.
pk
}
)
success_message
=
_
(
'Create asset permission <a href="{url}"> {name} </a> '
'success.'
.
format
(
url
=
url
,
name
=
self
.
object
.
name
)
)
return
success_message
class
AssetPermissionUpdateView
(
AdminUserRequiredMixin
,
SuccessMessageMixin
,
UpdateView
):
model
=
AssetPermission
form_class
=
AssetPermissionForm
template_name
=
'perms/asset_permission_create_update.html'
success_url
=
reverse_lazy
(
"perms:asset-permission-list"
)
success_message
=
update_success_msg
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
...
...
@@ -106,17 +63,6 @@ class AssetPermissionUpdateView(AdminUserRequiredMixin, SuccessMessageMixin, Upd
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
def
get_success_message
(
self
,
cleaned_data
):
url
=
reverse_lazy
(
'perms:asset-permission-detail'
,
kwargs
=
{
'pk'
:
self
.
object
.
pk
}
)
success_message
=
_
(
'Update asset permission <a href="{url}"> {name} </a> '
'success.'
.
format
(
url
=
url
,
name
=
self
.
object
.
name
)
)
return
success_message
class
AssetPermissionDetailView
(
AdminUserRequiredMixin
,
DetailView
):
template_name
=
'perms/asset_permission_detail.html'
...
...
This diff is collapsed.
Click to expand it.
apps/static/js/jumpserver.js
View file @
7f3d32a8
...
...
@@ -61,7 +61,6 @@ function GetTableDataBox() {
id_list
.
push
(
i
);
}
}
console
.
log
(
id_list
);
for
(
i
in
id_list
)
{
console
.
log
(
tabProduct
);
tableData
.
push
(
GetRowData
(
tabProduct
.
rows
[
id_list
[
i
]]));
...
...
@@ -357,5 +356,15 @@ String.prototype.format = function(args) {
function
setCookie
(
key
,
value
)
{
var
expires
=
new
Date
();
expires
.
setTime
(
expires
.
getTime
()
+
(
24
*
60
*
60
*
1000
));
document
.
cookie
=
key
+
'='
+
value
+
';expires='
+
expires
.
toUTCString
();
document
.
cookie
=
key
+
'='
+
value
+
';expires='
+
expires
.
toUTCString
()
+
';path=/'
;
}
function
delCookie
(
key
)
{
var
expires
=
new
Date
();
expires
.
setTime
(
expires
.
getTime
()
-
1
);
var
val
=
getCookie
(
key
);
if
(
val
!==
null
)
{
document
.
cookie
=
key
+
'='
+
val
+
";expires"
+
expires
.
toUTCString
()
+
';path=/'
;
}
}
This diff is collapsed.
Click to expand it.
apps/templates/_base_create_update.html
View file @
7f3d32a8
...
...
@@ -3,8 +3,8 @@
{% 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>
<link
href=
"{% static
'css/plugins/select2/select2.min.css'
%}"
rel=
"stylesheet"
>
<script
src=
"{% static
'js/plugins/select2/select2.full.min.js'
%}"
></script>
{% block custom_head_css_js_create %} {% endblock %}
{% endblock %}
...
...
This diff is collapsed.
Click to expand it.
apps/templates/_base_list.html
View file @
7f3d32a8
...
...
@@ -3,8 +3,8 @@
{% load i18n %}
{% block custom_head_css_js %}
<link
href=
"{% static "
css
/
plugins
/
datatables
/
datatables
.
min
.
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/select2/select2.min.css'
%}"
rel=
"stylesheet"
>
<script
src=
"{% static
'js/plugins/select2/select2.full.min.js'
%}"
></script>
<script
src=
"{% static "
js
/
plugins
/
datatables
/
datatables
.
min
.
js
"
%}"
></script>
{% endblock %}
{% block content %}
...
...
This diff is collapsed.
Click to expand it.
apps/templates/_header_bar.html
View file @
7f3d32a8
...
...
@@ -3,11 +3,11 @@
<nav
class=
"navbar navbar-static-top white-bg"
role=
"navigation"
style=
"margin-bottom: 0"
>
<div
class=
"navbar-header"
>
<a
class=
"navbar-minimalize minimalize-styl-2 btn btn-primary "
href=
"#"
><i
class=
"fa fa-bars"
></i>
</a>
<
form
role=
"search"
class=
"navbar-form-custom"
method=
"get"
action=
""
>
<
div
class=
"form-group"
>
<
input
type=
"text"
placeholder=
"{% trans 'Search' %}..."
class=
"form-control"
name=
"search"
id=
"top-search"
>
<
/div
>
<
/form
>
<
!--<form role="search" class="navbar-form-custom" method="get" action="">--
>
<
!--<div class="form-group">--
>
<
!--<input type="text" placeholder="{% trans 'Search' %}..." class="form-control" name="search" id="top-search">--
>
<
!--</div>--
>
<
!--</form>--
>
</div>
<ul
class=
"nav navbar-top-links navbar-right"
>
<li>
...
...
@@ -19,7 +19,7 @@
</a>
</li>
<li
class=
"dropdown"
>
{% if user.is_authenticated %}
{% if
request.
user.is_authenticated %}
<a
data-toggle=
"dropdown"
class=
"dropdown-toggle"
href=
"#"
>
<span
class=
"m-r-sm text-muted welcome-message"
>
<img
alt=
"image"
class=
"img-circle"
width=
"40"
height=
"40"
src=
"{{ request.user.avatar_url }}"
/>
...
...
@@ -30,17 +30,16 @@
</span>
</a>
<ul
class=
"dropdown-menu animated fadeInRight m-t-xs"
>
<li><a
href=
"{% url 'users:user-profile' %}"
>
{% trans 'Profile' %}
</a></li>
<li><a
href=
"{% url 'users:user-profile-update' %}"
>
{% trans 'Profile settings' %}
</a></li>
<li><a
href=
"{% url 'users:user-profile' %}"
><i
class=
"fa fa-cogs"
>
</i><span>
{% trans 'Profile' %}
</span></a></li>
<li
class=
"divider"
></li>
{% if request.user.is_superuser %}
{% if request.COOKIES.IN_ADMIN_PAGE == 'No' %}
<li><a
id=
"switch_admin"
>
{% trans 'Admin page' %}
</a></li>
{% else %}
<li><a
id=
"switch_user"
>
{% trans 'User page' %}
</a></li>
{% if request.COOKIES.IN_ADMIN_PAGE == 'No' %}
<li><a
id=
"switch_admin"
><i
class=
"fa fa-exchange"
></i><span>
{% trans 'Admin page' %}
</span></a></li>
{% else %}
<li><a
id=
"switch_user"
><i
class=
"fa fa-exchange"
></i><span>
{% trans 'User page' %}
</span></a></li>
{% endif %}
{% endif %}
{% endif %}
<li><a
href=
"{% url 'users:logout' %}"
>
{% trans 'Logout' %}
</a></li>
<li><a
href=
"{% url 'users:logout' %}"
><i
class=
"fa fa-sign-out"
></i>
{% trans 'Logout' %}
</a></li>
</ul>
{% else %}
<a
href=
"{% url 'users:login' %}"
>
...
...
This diff is collapsed.
Click to expand it.
apps/templates/_user_profile.html
View file @
7f3d32a8
...
...
@@ -18,16 +18,19 @@
$
(
document
).
ready
(
function
()
{
})
.
on
(
'click'
,
'#switch_admin'
,
function
()
{
var
cookieName
=
"IN_ADMIN_PAGE"
;
setTimeout
(
function
()
{
setCookie
(
"IN_ADMIN_PAGE"
,
"Yes"
);
delCookie
(
cookieName
);
setCookie
(
cookieName
,
"Yes"
);
window
.
location
=
"/"
},
100
)
})
.
on
(
'click'
,
'#switch_user'
,
function
()
{
var
cookieName
=
"IN_ADMIN_PAGE"
;
setTimeout
(
function
()
{
console
.
log
(
"Set to No"
);
setCookie
(
"IN_ADMIN_PAGE"
,
"No"
);
window
.
location
=
"
/
"
delCookie
(
cookieName
);
setCookie
(
cookieName
,
"No"
);
window
.
location
=
"
{% url 'assets:user-asset-list' %}
"
},
100
);
})
</script>
This diff is collapsed.
Click to expand it.
apps/terminal/api.py
View file @
7f3d32a8
...
...
@@ -110,7 +110,6 @@ class StatusViewSet(viewsets.ModelViewSet):
def
handle_sessions
(
self
):
sessions_active
=
[]
for
session_data
in
self
.
request
.
data
.
get
(
"sessions"
,
[]):
self
.
create_or_update_session
(
session_data
)
if
not
session_data
[
"is_finished"
]:
...
...
@@ -165,7 +164,7 @@ class StatusViewSet(viewsets.ModelViewSet):
class
SessionViewSet
(
viewsets
.
ModelViewSet
):
queryset
=
Session
.
objects
.
all
()
serializer
s
_class
=
SessionSerializer
serializer_class
=
SessionSerializer
permission_classes
=
(
IsSuperUserOrAppUser
,)
def
get_queryset
(
self
):
...
...
This diff is collapsed.
Click to expand it.
apps/terminal/forms.py
View file @
7f3d32a8
...
...
@@ -12,7 +12,6 @@ class TerminalForm(forms.ModelForm):
model
=
Terminal
fields
=
[
'name'
,
'remote_addr'
,
'ssh_port'
,
'http_port'
,
'comment'
]
help_texts
=
{
'remote_addr'
:
_
(
'A unique addr of every terminal, user browser can arrive it'
),
'ssh_port'
:
_
(
"Coco ssh listen port"
),
'http_port'
:
_
(
"Coco http/ws listen port"
),
}
...
...
This diff is collapsed.
Click to expand it.
apps/terminal/models.py
View file @
7f3d32a8
...
...
@@ -93,6 +93,7 @@ class Session(models.Model):
asset
=
models
.
CharField
(
max_length
=
1024
,
verbose_name
=
_
(
"Asset"
))
system_user
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
"System user"
))
login_from
=
models
.
CharField
(
max_length
=
2
,
choices
=
LOGIN_FROM_CHOICES
,
default
=
"ST"
)
remote_addr
=
models
.
CharField
(
max_length
=
15
,
verbose_name
=
_
(
"Remote addr"
),
blank
=
True
,
null
=
True
)
is_finished
=
models
.
BooleanField
(
default
=
False
)
has_replay
=
models
.
BooleanField
(
default
=
False
,
verbose_name
=
_
(
"Replay"
))
has_command
=
models
.
BooleanField
(
default
=
False
,
verbose_name
=
_
(
"Command"
))
...
...
This diff is collapsed.
Click to expand it.
apps/terminal/templates/terminal/session_detail.html
View file @
7f3d32a8
...
...
@@ -45,9 +45,9 @@
<thead>
<tr>
<th
data-toggle=
"true"
>
ID
</th>
<th>
Command
</th>
<th>
{% trans 'Command' %}
</th>
<th
data-hide=
"all"
></th>
<th>
Datetime
</th>
<th>
{% trans 'Datetime' %}
</th>
</tr>
</thead>
<tbody>
...
...
@@ -84,24 +84,24 @@
<table
class=
"table"
>
<tbody>
{% if object.is_finished %}
<tr>
<td
class=
"no-borders"
>
{% trans 'Replay session' %}:
</td>
<td
class=
"no-borders"
>
<tr
class=
"no-borders-tr"
>
<td>
{% trans 'Replay session' %}:
</td>
<td>
<span
class=
"pull-right"
>
<button
type=
"button"
class=
"btn btn-primary btn-xs"
id=
"btn_reset_password"
style=
"width: 54px"
>
{% trans 'Go' %}
</button>
<button
type=
"button"
onclick=
"window.open('/luna/replay/{{ object.id }}','luna', 'height=600, width=800, top=0, left=0, toolbar=no, menubar=no, scrollbars=no, location=no, status=no')"
class=
"btn btn-primary btn-xs"
id=
"btn_reset_password"
style=
"width: 54px"
>
{% trans 'Go' %}
</button>
</span>
</td>
</tr>
{% else %}
<
tr
>
<
td
class=
"no-borders"
>
{% trans 'Monitor session' %}:
</td
>
<
td
class=
"no-borders"
>
<
span
class=
"pull-right"
>
<
button
type=
"button"
class=
"btn btn-primary btn-xs "
style=
"width: 54px"
>
{% trans 'Go' %}
</button
>
<
/span
>
<
/td
>
<
/tr
>
<tr>
<
!--<tr>--
>
<
!--<td class="no-borders" >{% trans 'Monitor session' %}:</td>--
>
<
!--<td class="no-borders" >--
>
<
!--<span class="pull-right">--
>
<
!--<button type="button" class="btn btn-primary btn-xs " style="width: 54px">{% trans 'Go' %}</button>--
>
<
!--</span>--
>
<
!--</td>--
>
<
!--</tr>--
>
<tr
class=
"no-borders-tr"
>
<td>
{% trans 'Terminate session' %}:
</td>
<td>
<span
class=
"pull-right"
>
...
...
This diff is collapsed.
Click to expand it.
apps/terminal/templates/terminal/session_list.html
View file @
7f3d32a8
...
...
@@ -71,6 +71,7 @@
<th
class=
"text-center"
>
{% trans 'User' %}
</th>
<th
class=
"text-center"
>
{% trans 'Asset' %}
</th>
<th
class=
"text-center"
>
{% trans 'System user' %}
</th>
<th
class=
"text-center"
>
{% trans 'Remote addr' %}
</th>
<th
class=
"text-center"
>
{% trans 'Terminal' %}
</th>
<th
class=
"text-center"
>
{% trans 'Command' %}
</th>
<th
class=
"text-center"
>
{% trans 'Date start' %}
</th>
...
...
@@ -88,6 +89,7 @@
<td
class=
"text-center"
>
{{ session.user }}
</td>
<td
class=
"text-center"
>
{{ session.asset }}
</td>
<td
class=
"text-center"
>
{{ session.system_user }}
</td>
<td
class=
"text-center"
>
{{ session.remote_addr|default:"" }}
</td>
<td
class=
"text-center"
>
{{ session.terminal.name }}
</td>
<td
class=
"text-center"
>
{{ session.id | get_session_command_amount }}
</td>
...
...
@@ -97,7 +99,7 @@
{% if session.is_finished %}
<a
onclick=
"window.open('/luna/replay/{{ session.id }}','luna', 'height=600, width=800, top=0, left=0, toolbar=no, menubar=no, scrollbars=no, location=no, status=no')"
class=
"btn btn-xs btn-warning btn-replay"
>
{% trans "Replay" %}
</a>
{% else %}
<
a
onclick=
"window.open('/luna/monitor/{{ session.id }}','luna', 'height=600, width=800, top=0, left=0, toolbar=no, menubar=no, scrollbars=no, location=no, status=no')"
class=
"btn btn-xs btn-warning btn-monitor"
>
{% trans "Monitor" %}
</a
>
<
!--<a onclick="window.open('/luna/monitor/{{ session.id }}','luna', 'height=600, width=800, top=0, left=0, toolbar=no, menubar=no, scrollbars=no, location=no, status=no')" class="btn btn-xs btn-warning btn-monitor" >{% trans "Monitor" %}</a>--
>
<a
class=
"btn btn-xs btn-danger btn-term"
value=
"{{ session.id }}"
terminal=
"{{ session.terminal.id }}"
>
{% trans "Terminate" %}
</a>
{% endif %}
</td>
...
...
This diff is collapsed.
Click to expand it.
apps/terminal/templates/terminal/terminal_detail.html
View file @
7f3d32a8
...
...
@@ -13,7 +13,7 @@
<a
href=
""
class=
"text-center"
><i
class=
"fa fa-laptop"
></i>
{% trans 'Terminal detail' %}
</a>
</li>
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'terminal:terminal-update' pk=terminal.id %}"
><i
class=
"fa fa-edit"
></i>
Update
</a>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'terminal:terminal-update' pk=terminal.id %}"
><i
class=
"fa fa-edit"
></i>
{% trans 'Update' %}
</a>
</li>
</ul>
</div>
...
...
@@ -44,7 +44,7 @@
<td><b>
{{ terminal.name }}
</b></td>
</tr>
<tr>
<td>
{% trans 'Remote addr
ess
' %}:
</td>
<td>
{% trans 'Remote addr' %}:
</td>
<td><b>
{{ terminal.remote_addr }}
</b></td>
</tr>
<tr>
...
...
This diff is collapsed.
Click to expand it.
apps/terminal/templates/terminal/terminal_list.html
View file @
7f3d32a8
...
...
@@ -136,7 +136,6 @@ $(document).ready(function(){
}).
on
(
'click'
,
'.btn-connect'
,
function
()
{
var
$this
=
$
(
this
);
var
id
=
$this
.
data
(
'id'
);
console
.
log
(
id
)
})
</script>
{% endblock %}
This diff is collapsed.
Click to expand it.
apps/terminal/templates/terminal/terminal_update.html
View file @
7f3d32a8
...
...
@@ -3,8 +3,8 @@
{% 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>
<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
/
datepicker
/
datepicker3
.
css
"
%}"
rel=
"stylesheet"
>
{% endblock %}
...
...
This diff is collapsed.
Click to expand it.
apps/terminal/views/session.py
View file @
7f3d32a8
# -*- coding: utf-8 -*-
#
from
django.views.generic
import
ListView
,
UpdateView
,
DeleteView
,
DetailView
,
TemplateView
from
django.views.generic
import
ListView
from
django.views.generic.edit
import
SingleObjectMixin
from
django.utils.translation
import
ugettext
as
_
from
django.utils
import
timezone
...
...
@@ -51,9 +51,9 @@ class SessionListView(AdminUserRequiredMixin, DatetimeSearchMixin, ListView):
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'user_list'
:
utils
.
get_
user_list_from_cache
(),
'asset_list'
:
utils
.
get_
asset_list_from_cache
(),
'system_user_list'
:
utils
.
get_s
ystem_user_list_from_cache
(),
'user_list'
:
utils
.
get_
session_user_list
(),
'asset_list'
:
utils
.
get_
session_asset_list
(),
'system_user_list'
:
utils
.
get_s
ession_system_user_list
(),
'date_from'
:
self
.
date_from
,
'date_to'
:
self
.
date_to
,
'user'
:
self
.
user
,
...
...
This diff is collapsed.
Click to expand it.
apps/users/api.py
View file @
7f3d32a8
...
...
@@ -128,7 +128,7 @@ class UserAuthApi(APIView):
user_agent
=
request
.
data
.
get
(
'HTTP_USER_AGENT'
,
''
)
if
not
login_ip
:
login_ip
=
request
.
META
.
get
(
"REMOTE_ADDR"
)
login_ip
=
request
.
META
.
get
(
'HTTP_X_FORWARDED_FOR'
)
or
request
.
META
.
get
(
"REMOTE_ADDR"
)
user
,
msg
=
check_user_valid
(
username
=
username
,
password
=
password
,
...
...
This diff is collapsed.
Click to expand it.
apps/users/forms.py
View file @
7f3d32a8
...
...
@@ -29,7 +29,7 @@ class UserCreateUpdateForm(forms.ModelForm):
model
=
User
fields
=
[
'username'
,
'name'
,
'email'
,
'groups'
,
'wechat'
,
'phone'
,
'role'
,
'date_expired'
,
'comment'
,
'password'
'phone'
,
'role'
,
'date_expired'
,
'comment'
,
]
help_texts
=
{
'username'
:
'* required'
,
...
...
@@ -38,13 +38,16 @@ class UserCreateUpdateForm(forms.ModelForm):
}
widgets
=
{
'groups'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Join user groups'
)}),
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Join user groups'
)
}
),
}
def
save
(
self
,
commit
=
True
):
user
=
super
()
.
save
(
commit
=
commit
)
password
=
self
.
cleaned_data
.
get
(
'password'
)
user
=
super
()
.
save
(
commit
=
commit
)
if
password
:
user
.
set_password
(
password
)
user
.
save
()
...
...
@@ -184,12 +187,14 @@ class UserBulkUpdateForm(forms.ModelForm):
class
UserGroupForm
(
forms
.
ModelForm
):
users
=
forms
.
ModelMultipleChoiceField
(
queryset
=
User
.
objects
.
all
(),
label
=
_
(
"User"
),
widget
=
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select users'
)
}
)
),
required
=
False
,
)
def
__init__
(
self
,
**
kwargs
):
...
...
This diff is collapsed.
Click to expand it.
apps/users/models/user.py
View file @
7f3d32a8
...
...
@@ -168,6 +168,11 @@ class User(AbstractUser):
token
=
PrivateToken
.
objects
.
create
(
user
=
self
)
return
token
.
key
def
create_access_key
(
self
):
from
.
import
AccessKey
access_key
=
AccessKey
.
objects
.
create
(
user
=
self
)
return
access_key
def
refresh_private_token
(
self
):
from
.authentication
import
PrivateToken
PrivateToken
.
objects
.
filter
(
user
=
self
)
.
delete
()
...
...
@@ -214,13 +219,12 @@ class User(AbstractUser):
@classmethod
def
create_app_user
(
cls
,
name
,
comment
):
from
.
import
AccessKey
app
=
cls
.
objects
.
create
(
username
=
name
,
name
=
name
,
email
=
'{}@local.domain'
.
format
(
name
),
is_active
=
False
,
role
=
'App'
,
enable_otp
=
False
,
comment
=
comment
,
is_first_login
=
False
,
created_by
=
'System'
)
access_key
=
AccessKey
.
objects
.
create
(
user
=
app
)
access_key
=
app
.
create_access_key
(
)
return
app
,
access_key
@classmethod
...
...
This diff is collapsed.
Click to expand it.
apps/users/templates/users/user_detail.html
View file @
7f3d32a8
...
...
@@ -3,9 +3,9 @@
{% load i18n %}
{% block custom_head_css_js %}
<link
href=
"{% static
"
css
/
plugins
/
select2
/
select2
.
min
.
css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static
'css/plugins/select2/select2.min.css'
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
plugins
/
sweetalert
/
sweetalert
.
css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static
"
js
/
plugins
/
select2
/
select2
.
full
.
min
.
js
"
%}"
></script>
<script
src=
"{% static
'js/plugins/select2/select2.full.min.js'
%}"
></script>
<script
src=
"{% static "
js
/
plugins
/
sweetalert
/
sweetalert
.
min
.
js
"
%}"
></script>
{% endblock %}
{% block content %}
...
...
@@ -22,11 +22,11 @@
<a
href=
"{% url 'users:user-granted-asset' pk=user_object.id %}"
class=
"text-center"
><i
class=
"fa fa-cubes"
></i>
{% trans 'Asset granted' %}
</a>
</li>
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'users:user-update' pk=user_object.id %}"
><i
class=
"fa fa-edit"
></i>
Update
</a>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'users:user-update' pk=user_object.id %}"
><i
class=
"fa fa-edit"
></i>
{% trans 'Update' %}
</a>
</li>
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline btn-danger btn-delete-user"
>
<i
class=
"fa fa-
edit"
></i>
Delete
<i
class=
"fa fa-
trash-o"
></i>
{% trans 'Delete' %}
</a>
</li>
</ul>
...
...
This diff is collapsed.
Click to expand it.
apps/users/templates/users/user_group_create_update.html
View file @
7f3d32a8
...
...
@@ -3,8 +3,8 @@
{% load i18n %}
{% 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>
<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 %}
...
...
@@ -25,20 +25,6 @@
{% csrf_token %}
{% bootstrap_field form.name layout="horizontal" %}
{% bootstrap_field form.users layout="horizontal" %}
{#
<div
class=
"form-group"
>
#}
{#
<label
for=
"users"
class=
"col-sm-2 control-label"
>
{% trans 'Users' %}
</label>
#}
{#
<div
class=
"col-sm-9"
>
#}
{#
<select
name=
"users"
id=
"id_users"
data-placeholder=
"{% trans 'Select User' %}"
class=
"select2 form-control m-b"
multiple
tabindex=
"2"
>
#}
{# {% for user in users %}#}
{# {% if user.id in group_users %}#}
{#
<option
value=
"{{ user.id }}"
selected
>
{{ user.name }}
</option>
#}
{# {% else %}#}
{#
<option
value=
"{{ user.id }}"
>
{{ user.name }}
</option>
#}
{# {% endif %}#}
{# {% endfor %}#}
{#
</select>
#}
{#
</div>
#}
{#
</div>
#}
{% bootstrap_field form.comment layout="horizontal" %}
<div
class=
"form-group"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
...
...
@@ -57,7 +43,9 @@
{% block custom_foot_js %}
<script>
$
(
document
).
ready
(
function
()
{
$
(
'.select2'
).
select2
();
$
(
'.select2'
).
select2
({
closeOnSelect
:
false
});
})
</script>
{% endblock %}
This diff is collapsed.
Click to expand it.
apps/users/templates/users/user_group_detail.html
View file @
7f3d32a8
...
...
@@ -3,11 +3,11 @@
{% load i18n %}
{% block custom_head_css_js %}
<link
href=
"{% static
"
css
/
plugins
/
select2
/
select2
.
min
.
css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static
'css/plugins/select2/select2.min.css'
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
plugins
/
sweetalert
/
sweetalert
.
css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
plugins
/
datatables
/
datatables
.
min
.
css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
plugins
/
awesome-bootstrap-checkbox
/
awesome-bootstrap-checkbox
.
css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static
"
js
/
plugins
/
select2
/
select2
.
full
.
min
.
js
"
%}"
></script>
<script
src=
"{% static
'js/plugins/select2/select2.full.min.js'
%}"
></script>
<script
src=
"{% static "
js
/
plugins
/
sweetalert
/
sweetalert
.
min
.
js
"
%}"
></script>
<script
src=
"{% static "
js
/
plugins
/
datatables
/
datatables
.
min
.
js
"
%}"
></script>
{% endblock %}
...
...
@@ -25,11 +25,11 @@
{#
<a
href=
"{% url 'users:user-group-granted-asset' pk=user_group.id %}"
class=
"text-center"
><i
class=
"fa fa-cubes"
></i>
{% trans 'Asset granted' %}
</a>
#}
{#
</li>
#}
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'users:user-group-update' pk=user_group.id %}"
><i
class=
"fa fa-edit"
></i>
Update
</a>
<a
class=
"btn btn-outline btn-default"
href=
"{% url 'users:user-group-update' pk=user_group.id %}"
><i
class=
"fa fa-edit"
></i>
{% trans 'Update' %}
</a>
</li>
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline btn-danger btn-delete-user-group"
>
<i
class=
"fa fa-
edit"
></i>
Delete
<i
class=
"fa fa-
trash-o"
></i>
{% trans 'Delete' %}
</a>
</li>
</ul>
...
...
@@ -171,7 +171,6 @@ $(document).ready(function () {
var
users
=
$
(
'.bdg_user'
).
map
(
function
()
{
return
$
(
this
).
data
(
'uid'
);
}).
get
();
console
.
log
(
users
);
updateGroupMember
(
users
)
}).
on
(
'click'
,
'#btn_add_user'
,
function
()
{
if
(
Object
.
keys
(
jumpserver
.
users_selected
).
length
===
0
)
{
...
...
This diff is collapsed.
Click to expand it.
apps/users/templates/users/user_group_granted_asset.html
View file @
7f3d32a8
...
...
@@ -4,8 +4,8 @@
{% 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>
<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"
>
...
...
This diff is collapsed.
Click to expand it.
apps/users/templates/users/user_list.html
View file @
7f3d32a8
...
...
@@ -223,7 +223,7 @@ $(document).ready(function(){
var
$this
=
$
(
this
);
var
name
=
$this
.
data
(
'name'
);
var
uid
=
$this
.
data
(
'uid'
);
var
the_url
=
'{% url "api-users:user-detail" pk=
'
00000000
-
0000
-
0000
-
0000
-
000000000000
' %}'
.
replace
(
'00000000-0000-0000-0000-000000000000'
,
uid
);
var
the_url
=
'{% url "api-users:user-detail" pk=
DEFAULT_PK %}'
.
replace
(
"{{ DEFAULT_PK }}"
,
uid
);
objectDelete
(
$this
,
name
,
the_url
);
})
</script>
...
...
This diff is collapsed.
Click to expand it.
apps/users/views/group.py
View file @
7f3d32a8
...
...
@@ -2,17 +2,15 @@
from
__future__
import
unicode_literals
from
django
import
forms
from
django.shortcuts
import
reverse
,
redirect
from
django.utils.translation
import
ugettext
as
_
from
django.urls
import
reverse_lazy
from
django.views.generic
import
ListView
from
django.views.generic.base
import
TemplateView
from
django.views.generic.edit
import
CreateView
,
UpdateView
,
FormMixin
from
django.views.generic.detail
import
DetailView
,
SingleObjectMixin
from
django.views.generic.edit
import
CreateView
,
UpdateView
from
django.views.generic.detail
import
DetailView
from
django.contrib.messages.views
import
SuccessMessageMixin
from
common.utils
import
get_logger
from
perms.models
import
AssetPermission
from
common.const
import
create_success_msg
,
update_success_msg
from
..models
import
User
,
UserGroup
from
..utils
import
AdminUserRequiredMixin
from
..
import
forms
...
...
@@ -39,7 +37,7 @@ class UserGroupCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateVie
form_class
=
forms
.
UserGroupForm
template_name
=
'users/user_group_create_update.html'
success_url
=
reverse_lazy
(
'users:user-group-list'
)
success_message
=
'<a href={url}> {name} </a> was created successfully'
success_message
=
create_success_msg
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
...
...
@@ -49,21 +47,13 @@ class UserGroupCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateVie
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
def
get_success_message
(
self
,
cleaned_data
):
url
=
reverse_lazy
(
'users:user-group-detail'
,
kwargs
=
{
'pk'
:
self
.
object
.
id
}
)
return
self
.
success_message
.
format
(
url
=
url
,
name
=
self
.
object
.
name
)
class
UserGroupUpdateView
(
AdminUserRequiredMixin
,
UpdateView
):
class
UserGroupUpdateView
(
AdminUserRequiredMixin
,
SuccessMessageMixin
,
UpdateView
):
model
=
UserGroup
form_class
=
forms
.
UserGroupForm
template_name
=
'users/user_group_create_update.html'
success_url
=
reverse_lazy
(
'users:user-group-list'
)
success_message
=
update_success_msg
def
get_context_data
(
self
,
**
kwargs
):
users
=
User
.
objects
.
all
()
...
...
This diff is collapsed.
Click to expand it.
apps/users/views/login.py
View file @
7f3d32a8
...
...
@@ -53,7 +53,8 @@ class UserLoginView(FormView):
if
not
self
.
request
.
session
.
test_cookie_worked
():
return
HttpResponse
(
_
(
"Please enable cookies and try again."
))
auth_login
(
self
.
request
,
form
.
get_user
())
login_ip
=
self
.
request
.
META
.
get
(
'REMOTE_ADDR'
,
''
)
login_ip
=
self
.
request
.
META
.
get
(
'HTTP_X_FORWARDED_FOR'
)
or
\
self
.
request
.
META
.
get
(
'REMOTE_ADDR'
,
''
)
user_agent
=
self
.
request
.
META
.
get
(
'HTTP_USER_AGENT'
,
''
)
write_login_log_async
.
delay
(
self
.
request
.
user
.
username
,
type
=
'W'
,
...
...
@@ -82,6 +83,7 @@ class UserLogoutView(TemplateView):
context
=
{
'title'
:
_
(
'Logout success'
),
'messages'
:
_
(
'Logout success, return login page'
),
'interval'
:
1
,
'redirect_url'
:
reverse
(
'users:login'
),
'auto_redirect'
:
True
,
}
...
...
This diff is collapsed.
Click to expand it.
apps/users/views/user.py
View file @
7f3d32a8
...
...
@@ -27,12 +27,14 @@ from django.views.generic.detail import DetailView, SingleObjectMixin
from
django.views.decorators.csrf
import
csrf_exempt
from
django.contrib.auth
import
logout
as
auth_logout
from
common.const
import
create_success_msg
,
update_success_msg
from
common.mixins
import
JSONResponseMixin
from
common.utils
import
get_logger
,
get_object_or_none
,
is_uuid
from
..
import
forms
from
..models
import
User
,
UserGroup
from
..utils
import
AdminUserRequiredMixin
from
..signals
import
on_user_created
from
common.mixins
import
JSONResponseMixin
from
common.utils
import
get_logger
,
get_object_or_none
,
is_uuid
__all__
=
[
'UserListView'
,
'UserCreateView'
,
'UserDetailView'
,
...
...
@@ -63,7 +65,7 @@ class UserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView):
form_class
=
forms
.
UserCreateUpdateForm
template_name
=
'users/user_create.html'
success_url
=
reverse_lazy
(
'users:user-list'
)
success_message
=
_
(
'Create user <a href="{url}">{name}</a> successfully.'
)
success_message
=
create_success_msg
def
get_context_data
(
self
,
**
kwargs
):
context
=
super
()
.
get_context_data
(
**
kwargs
)
...
...
@@ -77,19 +79,14 @@ class UserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView):
on_user_created
.
send
(
self
.
__class__
,
user
=
user
)
return
super
()
.
form_valid
(
form
)
def
get_success_message
(
self
,
cleaned_data
):
url
=
reverse_lazy
(
'users:user-detail'
,
kwargs
=
{
'pk'
:
self
.
object
.
pk
})
return
self
.
success_message
.
format
(
url
=
url
,
name
=
self
.
object
.
name
)
class
UserUpdateView
(
AdminUserRequiredMixin
,
UpdateView
):
class
UserUpdateView
(
AdminUserRequiredMixin
,
SuccessMessageMixin
,
UpdateView
):
model
=
User
form_class
=
forms
.
UserCreateUpdateForm
template_name
=
'users/user_update.html'
context_object_name
=
'user_object'
success_url
=
reverse_lazy
(
'users:user-list'
)
success_message
=
update_success_msg
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
_
(
'Users'
),
'action'
:
_
(
'Update user'
)}
...
...
@@ -332,17 +329,10 @@ class UserProfileUpdateView(LoginRequiredMixin, UpdateView):
model
=
User
form_class
=
forms
.
UserProfileForm
success_url
=
reverse_lazy
(
'users:user-profile'
)
success_message
=
_
(
'Create user <a href="{url}">{name}</a> successfully.'
)
def
get_object
(
self
,
queryset
=
None
):
return
self
.
request
.
user
def
get_success_message
(
self
,
cleaned_data
):
url
=
reverse_lazy
(
'users:user-detail'
,
kwargs
=
{
'pk'
:
self
.
object
.
pk
})
return
self
.
success_message
.
format
(
url
=
url
,
name
=
self
.
object
.
name
)
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
_
(
'User'
),
...
...
This diff is collapsed.
Click to expand it.
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