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
Jan 10, 2018
by
q4speed
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/dev' into dev
parents
6d7b5968
b2b123b4
Hide whitespace changes
Inline
Side-by-side
Showing
84 changed files
with
1099 additions
and
1032 deletions
+1099
-1032
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
+471
-443
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"
})
...
...
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'
)
,
}
...
...
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
):
...
...
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
):
...
...
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
):
...
...
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
):
...
...
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
...
...
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
=
[]
...
...
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
(
...
...
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 %}
...
...
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>
...
...
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 %}
...
...
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
(
...
...
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
);
})
...
...
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 %}
...
...
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
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
);
})
...
...
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?' %}"
,
...
...
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
)
{
...
...
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" %}
...
...
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 %}
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
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>
...
...
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>
...
...
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>
...
...
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 %}
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"
},
...
...
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/$'
,
...
...
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
...
...
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
...
...
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
)
...
...
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
):
...
...
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
)
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
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
...
...
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
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'
:
''
,
}
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
)
apps/locale/zh/LC_MESSAGES/django.mo
View file @
7f3d32a8
No preview for this file type
apps/locale/zh/LC_MESSAGES/django.po
View file @
7f3d32a8
...
...
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Jumpserver 0.3.3\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-01-
01 15:33
+0800\n"
"POT-Creation-Date: 2018-01-
10 00:30
+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: Jumpserver team<ibuler@qq.com>\n"
...
...
@@ -17,8 +17,8 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: assets/forms.py:23 assets/forms.py:53 assets/forms.py:99 perms/forms.py:3
6
#: perms/templates/perms/asset_permission_asset.html:1
27 users/forms.py:240
#: assets/forms.py:23 assets/forms.py:53 assets/forms.py:99 perms/forms.py:3
7
#: perms/templates/perms/asset_permission_asset.html:1
16 users/forms.py:242
msgid "Select asset groups"
msgstr "选择资产组"
...
...
@@ -36,19 +36,19 @@ msgstr "主机级别管理用户,如果没有设置则默认使用集群级别
#: assets/forms.py:40 assets/forms.py:68
msgid "You need set a admin user if cluster not have"
msgstr ""
msgstr "
集群没有管理用户,你需要为集群设置管理用户或设置一个主机级别的管理用户
"
#: assets/forms.py:54
msgid "Default using cluster admin user"
msgstr "默认使用管理用户"
#: assets/forms.py:76 assets/forms.py:81 assets/forms.py:127
#: assets/templates/assets/asset_group_detail.html:70 perms/forms.py:3
3
#: perms/templates/perms/asset_permission_asset.html:
99 users/forms.py:237
#: assets/templates/assets/asset_group_detail.html:70 perms/forms.py:3
4
#: perms/templates/perms/asset_permission_asset.html:
88 users/forms.py:239
msgid "Select assets"
msgstr "选择资产"
#: assets/forms.py:86 assets/models/asset.py:
4
5
#: assets/forms.py:86 assets/models/asset.py:
5
5
#: assets/templates/assets/admin_user_assets.html:61
#: assets/templates/assets/asset_detail.html:69
#: assets/templates/assets/asset_group_detail.html:47
...
...
@@ -56,12 +56,13 @@ msgstr "选择资产"
#: assets/templates/assets/cluster_assets.html:53
#: assets/templates/assets/system_user_asset.html:54
#: assets/templates/assets/user_asset_list.html:21
#: perms/templates/perms/asset_permission_asset.html:56
#: users/templates/users/user_group_granted_asset.html:51
msgid "Port"
msgstr "端口"
#: assets/forms.py:124 assets/templates/assets/asset_group_list.html:16
#: assets/forms.py:124 assets/models/asset.py:171
#: assets/templates/assets/admin_user_list.html:24
#: assets/templates/assets/asset_group_list.html:16
#: assets/templates/assets/system_user_list.html:26 perms/models.py:17
#: perms/templates/perms/asset_permission_create_update.html:40
#: perms/templates/perms/asset_permission_list.html:28 templates/_nav.html:22
...
...
@@ -75,7 +76,22 @@ msgstr "端口"
msgid "Asset"
msgstr "资产"
#: assets/forms.py:159 assets/forms.py:219 assets/forms.py:278
#: assets/forms.py:161 perms/forms.py:40
#: perms/templates/perms/asset_permission_detail.html:144 users/forms.py:245
msgid "Select system users"
msgstr "选择系统用户"
#: assets/forms.py:163
#: assets/templates/assets/_asset_group_bulk_update_modal.html:22
#: assets/templates/assets/cluster_list.html:22
msgid "System users"
msgstr "系统用户"
#: assets/forms.py:165
msgid "Selected system users will be create at cluster assets"
msgstr "选择的系统用户将会在该集群资产上创建"
#: assets/forms.py:173 assets/forms.py:248 assets/forms.py:308
#: assets/models/cluster.py:18 assets/models/group.py:20
#: assets/models/user.py:28 assets/templates/assets/admin_user_detail.html:56
#: assets/templates/assets/admin_user_list.html:22
...
...
@@ -84,13 +100,13 @@ msgstr "资产"
#: assets/templates/assets/cluster_list.html:19
#: assets/templates/assets/system_user_detail.html:53
#: assets/templates/assets/system_user_list.html:24 ops/models.py:31
#: ops/templates/ops/task_detail.html:56 ops/templates/ops/task_list.html:3
9
#: ops/templates/ops/task_detail.html:56 ops/templates/ops/task_list.html:3
4
#: perms/models.py:14
#: perms/templates/perms/asset_permission_create_update.html:33
#: perms/templates/perms/asset_permission_detail.html:62
#: perms/templates/perms/asset_permission_list.html:25
#: perms/templates/perms/asset_permission_user.html:54 terminal/models.py:14
#: terminal/models.py:11
7
terminal/templates/terminal/terminal_detail.html:43
#: terminal/models.py:11
8
terminal/templates/terminal/terminal_detail.html:43
#: terminal/templates/terminal/terminal_list.html:29 users/models/group.py:14
#: users/models/user.py:36 users/templates/users/_select_user_modal.html:13
#: users/templates/users/user_detail.html:62
...
...
@@ -104,19 +120,37 @@ msgstr "资产"
msgid "Name"
msgstr "名称"
#: assets/forms.py:174
#: assets/forms.py:179
msgid "Cluster level admin user"
msgstr "集群级别管理用户"
#: assets/forms.py:200
msgid "Password or private key password"
msgstr "密码或秘钥不合法"
#: assets/forms.py:202 assets/forms.py:260 assets/forms.py:321
#: assets/forms.py:201 assets/forms.py:262 assets/models/user.py:30
#: users/forms.py:16 users/forms.py:24 users/templates/users/login.html:56
#: users/templates/users/reset_password.html:52
#: users/templates/users/user_create.html:11
#: users/templates/users/user_password_update.html:40
#: users/templates/users/user_profile_update.html:40
#: users/templates/users/user_pubkey_update.html:40
msgid "Password"
msgstr "密码"
#: assets/forms.py:204 assets/forms.py:264 users/models/user.py:46
msgid "Private key"
msgstr "ssh私钥"
#: assets/forms.py:229 assets/forms.py:290 assets/forms.py:354
msgid "Invalid private key"
msgstr "ssh密钥不合法"
#: assets/forms.py:2
12
#: assets/forms.py:2
40
msgid "Password and private key file must be input one"
msgstr "密码和私钥, 必须输入一个"
#: assets/forms.py:2
20 assets/forms.py:27
9 assets/models/user.py:29
#: assets/forms.py:2
49 assets/forms.py:30
9 assets/models/user.py:29
#: assets/templates/assets/admin_user_detail.html:60
#: assets/templates/assets/admin_user_list.html:23
#: assets/templates/assets/system_user_detail.html:57
...
...
@@ -132,59 +166,73 @@ msgstr "密码和私钥, 必须输入一个"
msgid "Username"
msgstr "用户名"
#: assets/forms.py:2
67 assets/forms.py:327
#: assets/forms.py:2
97 assets/forms.py:360
msgid "Auth info required, private_key or password"
msgstr "密钥和密码必须填写一个"
#: assets/forms.py:
282
#: assets/forms.py:
313
msgid " Select clusters"
msgstr "选择集群"
#: assets/models/asset.py:24
#: assets/forms.py:320
msgid "If auto push checked, system user will be create at cluster assets"
msgstr "如果选择了自动推送,系统用户将会创建在集群资产上"
#: assets/forms.py:321
msgid "Auto push system user to asset"
msgstr "自动推送系统用户到资产"
#: assets/forms.py:322
msgid ""
"High level will be using login asset as default, if user was granted more "
"than 2 system user"
msgstr "高优先级的系统用户将会作为默认登录用户"
#: assets/models/asset.py:34
msgid "In use"
msgstr "使用中"
#: assets/models/asset.py:
2
5
#: assets/models/asset.py:
3
5
msgid "Out of use"
msgstr "未使用"
#: assets/models/asset.py:
2
8
#: assets/models/asset.py:
3
8
msgid "Server"
msgstr "物理机"
#: assets/models/asset.py:
2
9
#: assets/models/asset.py:
3
9
msgid "VM"
msgstr "虚拟机"
#: assets/models/asset.py:
3
0
#: assets/models/asset.py:
4
0
msgid "Switch"
msgstr "交换机"
#: assets/models/asset.py:
3
1
#: assets/models/asset.py:
4
1
msgid "Router"
msgstr "路由器"
#: assets/models/asset.py:
3
2
#: assets/models/asset.py:
4
2
msgid "Firewall"
msgstr "防火墙"
#: assets/models/asset.py:
3
3
#: assets/models/asset.py:
4
3
msgid "Storage"
msgstr "存储"
#: assets/models/asset.py:
3
6
#: assets/models/asset.py:
4
6
msgid "Production"
msgstr "生产环境"
#: assets/models/asset.py:
3
7
#: assets/models/asset.py:
4
7
msgid "Development"
msgstr "开发环境"
#: assets/models/asset.py:
3
8
#: assets/models/asset.py:
4
8
msgid "Testing"
msgstr "测试环境"
#: assets/models/asset.py:
4
3 assets/templates/assets/admin_user_assets.html:60
#: assets/models/asset.py:
5
3 assets/templates/assets/admin_user_assets.html:60
#: assets/templates/assets/asset_detail.html:61
#: assets/templates/assets/asset_group_detail.html:46
#: assets/templates/assets/asset_list.html:31
...
...
@@ -198,7 +246,7 @@ msgstr "测试环境"
msgid "IP"
msgstr "IP"
#: assets/models/asset.py:
4
4 assets/templates/assets/admin_user_assets.html:59
#: assets/models/asset.py:
5
4 assets/templates/assets/admin_user_assets.html:59
#: assets/templates/assets/asset_detail.html:57
#: assets/templates/assets/asset_group_detail.html:45
#: assets/templates/assets/asset_list.html:30
...
...
@@ -211,116 +259,116 @@ msgstr "IP"
msgid "Hostname"
msgstr "主机名"
#: assets/models/asset.py:
4
6 assets/templates/assets/asset_detail.html:213
#: assets/views/asset.py:21
2 assets/views/asset.py:252
#: assets/models/asset.py:
5
6 assets/templates/assets/asset_detail.html:213
#: assets/views/asset.py:21
8 assets/views/asset.py:258
msgid "Asset groups"
msgstr "资产组"
#: assets/models/asset.py:
47 assets/models/user.py:215
#: assets/templates/assets/asset_detail.html:85
#: assets/models/asset.py:
57 assets/models/cluster.py:40
#: assets/
models/user.py:219 assets/
templates/assets/asset_detail.html:85
#: assets/templates/assets/asset_list.html:33 templates/_nav.html:24
msgid "Cluster"
msgstr "集群"
#: assets/models/asset.py:
4
8 assets/templates/assets/asset_detail.html:129
#: assets/models/asset.py:
5
8 assets/templates/assets/asset_detail.html:129
msgid "Is active"
msgstr "激活"
#: assets/models/asset.py:
4
9 assets/templates/assets/asset_detail.html:133
#: assets/models/asset.py:
5
9 assets/templates/assets/asset_detail.html:133
msgid "Asset type"
msgstr "系统类型"
#: assets/models/asset.py:
5
0 assets/templates/assets/asset_detail.html:137
#: assets/models/asset.py:
6
0 assets/templates/assets/asset_detail.html:137
msgid "Asset environment"
msgstr "资产环境"
#: assets/models/asset.py:
5
1 assets/templates/assets/asset_detail.html:125
#: assets/models/asset.py:
6
1 assets/templates/assets/asset_detail.html:125
msgid "Asset status"
msgstr "资产状态"
#: assets/models/asset.py:
5
4 assets/models/cluster.py:19
#: assets/templates/assets/asset_detail.html:73
#: assets/models/asset.py:
6
4 assets/models/cluster.py:19
#: assets/
models/user.py:190 assets/
templates/assets/asset_detail.html:73
#: assets/templates/assets/cluster_list.html:20 templates/_nav.html:25
msgid "Admin user"
msgstr "管理用户"
#: assets/models/asset.py:
5
7 assets/templates/assets/asset_detail.html:65
#: assets/models/asset.py:
6
7 assets/templates/assets/asset_detail.html:65
msgid "Public IP"
msgstr "公网IP"
#: assets/models/asset.py:
5
8
#: assets/models/asset.py:
6
8
msgid "Remote control card IP"
msgstr "远控卡IP"
#: assets/models/asset.py:
5
9 assets/templates/assets/asset_detail.html:89
#: assets/models/asset.py:
6
9 assets/templates/assets/asset_detail.html:89
msgid "Cabinet number"
msgstr "机柜编号"
#: assets/models/asset.py:
6
0 assets/templates/assets/asset_detail.html:93
#: assets/models/asset.py:
7
0 assets/templates/assets/asset_detail.html:93
msgid "Cabinet position"
msgstr "机柜层号"
#: assets/models/asset.py:
6
1 assets/templates/assets/asset_detail.html:145
#: assets/models/asset.py:
7
1 assets/templates/assets/asset_detail.html:145
msgid "Asset number"
msgstr "资产编号"
#: assets/models/asset.py:
6
4 assets/templates/assets/asset_detail.html:97
#: assets/models/asset.py:
7
4 assets/templates/assets/asset_detail.html:97
msgid "Vendor"
msgstr "制造商"
#: assets/models/asset.py:
6
5 assets/templates/assets/asset_detail.html:101
#: assets/models/asset.py:
7
5 assets/templates/assets/asset_detail.html:101
msgid "Model"
msgstr "型号"
#: assets/models/asset.py:
6
6 assets/templates/assets/asset_detail.html:141
#: assets/models/asset.py:
7
6 assets/templates/assets/asset_detail.html:141
msgid "Serial number"
msgstr "序列号"
#: assets/models/asset.py:
6
8
#: assets/models/asset.py:
7
8
msgid "CPU model"
msgstr "CPU型号"
#: assets/models/asset.py:
6
9
#: assets/models/asset.py:
7
9
msgid "CPU count"
msgstr "CPU数量"
#: assets/models/asset.py:
7
0
#: assets/models/asset.py:
8
0
msgid "CPU cores"
msgstr "CPU核数"
#: assets/models/asset.py:
7
1 assets/templates/assets/asset_detail.html:109
#: assets/models/asset.py:
8
1 assets/templates/assets/asset_detail.html:109
msgid "Memory"
msgstr "内存"
#: assets/models/asset.py:
7
2
#: assets/models/asset.py:
8
2
msgid "Disk total"
msgstr "硬盘大小"
#: assets/models/asset.py:
7
3
#: assets/models/asset.py:
8
3
msgid "Disk info"
msgstr "硬盘信息"
#: assets/models/asset.py:
7
5 assets/templates/assets/asset_detail.html:117
#: assets/models/asset.py:
8
5 assets/templates/assets/asset_detail.html:117
msgid "Platform"
msgstr "系统平台"
#: assets/models/asset.py:
7
6 assets/templates/assets/asset_detail.html:121
#: assets/models/asset.py:
8
6 assets/templates/assets/asset_detail.html:121
msgid "OS"
msgstr "操作系统"
#: assets/models/asset.py:
7
7
#: assets/models/asset.py:
8
7
msgid "OS version"
msgstr "系统版本"
#: assets/models/asset.py:
7
8
#: assets/models/asset.py:
8
8
msgid "OS arch"
msgstr "系统架构"
#: assets/models/asset.py:
7
9
#: assets/models/asset.py:
8
9
msgid "Hostname raw"
msgstr "主机名原始"
#: assets/models/asset.py:
8
1 assets/models/cluster.py:28
#: assets/models/asset.py:
9
1 assets/models/cluster.py:28
#: assets/models/group.py:21 assets/models/user.py:36
#: assets/templates/assets/admin_user_detail.html:68
#: assets/templates/assets/asset_detail.html:149
...
...
@@ -332,7 +380,7 @@ msgstr "主机名原始"
msgid "Created by"
msgstr "创建者"
#: assets/models/asset.py:
8
2 assets/models/cluster.py:26
#: assets/models/asset.py:
9
2 assets/models/cluster.py:26
#: assets/models/group.py:22 assets/templates/assets/admin_user_detail.html:64
#: assets/templates/assets/cluster_detail.html:89
#: assets/templates/assets/system_user_detail.html:87
...
...
@@ -343,10 +391,10 @@ msgstr "创建者"
msgid "Date created"
msgstr "创建日期"
#: assets/models/asset.py:
8
3 assets/models/cluster.py:29
#: assets/models/asset.py:
9
3 assets/models/cluster.py:29
#: assets/models/group.py:23 assets/models/user.py:33
#: assets/templates/assets/admin_user_detail.html:72
#: assets/templates/assets/admin_user_list.html:2
6
#: assets/templates/assets/admin_user_list.html:2
8
#: assets/templates/assets/asset_detail.html:157
#: assets/templates/assets/asset_group_list.html:17
#: assets/templates/assets/cluster_detail.html:97
...
...
@@ -391,11 +439,11 @@ msgstr "外网"
msgid "Operator"
msgstr "运营商"
#: assets/models/cluster.py:36 assets/models/group.py:3
3
#: assets/models/cluster.py:36 assets/models/group.py:3
4
msgid "Default"
msgstr "默认"
#: assets/models/cluster.py:36 users/models/user.py:2
59
#: assets/models/cluster.py:36 users/models/user.py:2
63
msgid "System"
msgstr "系统"
...
...
@@ -403,20 +451,15 @@ msgstr "系统"
msgid "Default Cluster"
msgstr "默认Cluster"
#: assets/models/group.py:33
#: assets/models/group.py:30 perms/models.py:18
#: perms/templates/perms/asset_permission_list.html:29 templates/_nav.html:23
msgid "Asset group"
msgstr "资产组"
#: assets/models/group.py:34
msgid "Default asset group"
msgstr "默认资产组"
#: assets/models/user.py:30 users/forms.py:16 users/forms.py:24
#: users/templates/users/login.html:56
#: users/templates/users/reset_password.html:52
#: users/templates/users/user_create.html:11
#: users/templates/users/user_password_update.html:40
#: users/templates/users/user_profile_update.html:40
#: users/templates/users/user_pubkey_update.html:40
msgid "Password"
msgstr "密码"
#: assets/models/user.py:31
msgid "SSH private key"
msgstr "ssh密钥"
...
...
@@ -425,42 +468,55 @@ msgstr "ssh密钥"
msgid "SSH public key"
msgstr "ssh公钥"
#: assets/models/user.py:2
16
#: assets/models/user.py:2
20
msgid "Priority"
msgstr ""
msgstr "
优先级
"
#: assets/models/user.py:2
17
assets/templates/assets/system_user_detail.html:61
#: assets/models/user.py:2
21
assets/templates/assets/system_user_detail.html:61
msgid "Protocol"
msgstr "协议"
#: assets/models/user.py:2
18
assets/templates/assets/_system_user.html:59
#: assets/models/user.py:2
22
assets/templates/assets/_system_user.html:59
#: assets/templates/assets/system_user_detail.html:113
#: assets/templates/assets/system_user_update.html:11
msgid "Auto push"
msgstr "自动推送"
#: assets/models/user.py:2
19
assets/templates/assets/system_user_detail.html:65
#: assets/models/user.py:2
23
assets/templates/assets/system_user_detail.html:65
msgid "Sudo"
msgstr "Sudo"
#: assets/models/user.py:22
0
assets/templates/assets/system_user_detail.html:70
#: assets/models/user.py:22
4
assets/templates/assets/system_user_detail.html:70
msgid "Shell"
msgstr "Shell"
#: assets/models/user.py:269 perms/models.py:19
#: perms/templates/perms/asset_permission_detail.html:136
#: perms/templates/perms/asset_permission_list.html:30 templates/_nav.html:26
#: terminal/backends/command/models.py:12 terminal/models.py:94
#: terminal/templates/terminal/command_list.html:48
#: terminal/templates/terminal/command_list.html:74
#: terminal/templates/terminal/session_list.html:49
#: terminal/templates/terminal/session_list.html:73
#: users/templates/users/user_granted_asset.html:50
#: users/templates/users/user_group_granted_asset.html:52
msgid "System user"
msgstr "系统用户"
#: assets/models/utils.py:29
#, python-format
msgid "%(value)s is not an even number"
msgstr "%(value)s is not an even number"
#: assets/signals_handler.py:3
1
#: assets/signals_handler.py:3
2
msgid "Push cluster system users to asset"
msgstr "推送集群系统用户到资产"
#: assets/signals_handler.py:6
3 assets/signals_handler.py:125
#: assets/signals_handler.py:6
4 assets/signals_handler.py:126
msgid "Push system user to cluster assets: {}->{}"
msgstr "推送系统用户到: {}->{}"
#: assets/signals_handler.py:10
2
#: assets/signals_handler.py:10
3
msgid "Push system user to assets"
msgstr "推送系统用户到资产"
...
...
@@ -478,23 +534,31 @@ msgstr "定期更新资产硬件信息"
#: assets/tasks.py:189
msgid "Test admin user connectability period: {}"
msgstr "定期测试管理用户可
以连接性
"
msgstr "定期测试管理用户可
连接性: {}
"
#: assets/tasks.py:203
msgid "Test admin user connectability: {}"
msgstr "测试管理用户可连接性: {}"
#: assets/tasks.py:289
msgid "Test system user connectability period: {}"
#: assets/tasks.py:212
msgid "Test asset connectability"
msgstr "测试资产可连接性"
#: assets/tasks.py:283
msgid "Test system user connectability: {}"
msgstr "测试系统用户可连接性: {}"
#: assets/tasks.py:363
#: assets/tasks.py:295
msgid "Test system user connectability period: {}"
msgstr "定期测试系统用户可连接性: {}"
#: assets/tasks.py:376
msgid "Push system user to cluster assets: {}"
msgstr "推送系统用户到资产: {}"
#: assets/tasks.py:3
84
msgid "Push
system user to cluster assets period: {}->
{}"
msgstr "定期推送
系统用户到资产: {}->
{}"
#: assets/tasks.py:3
97
msgid "Push
cluster system users to assets period:
{}"
msgstr "定期推送
集群系统用户到资产:
{}"
#: assets/templates/assets/_asset_group_bulk_update_modal.html:5
msgid "Update asset group"
...
...
@@ -506,16 +570,16 @@ msgstr "仅修改你需要更新的字段"
#: assets/templates/assets/_asset_group_bulk_update_modal.html:12
#: assets/templates/assets/system_user_asset.html:21
#: assets/views/admin_user.py:2
7 assets/views/admin_user.py:44
#: assets/views/admin_user.py:6
7 assets/views/admin_user.py:88
#: assets/views/admin_user.py:1
15 assets/views/asset.py:47
#: assets/views/asset.py:61 assets/views/asset.py:84 assets/views/asset.py:14
1
#: assets/views/asset.py:1
58 assets/views/asset.py:179
#: assets/views/cluster.py:2
2 assets/views/cluster.py:80
#: assets/views/cluster.py:
97 assets/views/group.py:30 assets/views/group.py:53
#: assets/views/group.py:
71 assets/views/group.py:93
#: assets/views/system_user.py:2
9 assets/views/system_user.py:48
#: assets/views/system_user.py:
71 assets/views/system_user.py:91
#: assets/views/admin_user.py:2
9 assets/views/admin_user.py:47
#: assets/views/admin_user.py:6
3 assets/views/admin_user.py:79
#: assets/views/admin_user.py:1
06 assets/views/asset.py:48
#: assets/views/asset.py:61 assets/views/asset.py:84 assets/views/asset.py:14
4
#: assets/views/asset.py:1
61 assets/views/asset.py:185
#: assets/views/cluster.py:2
6 assets/views/cluster.py:85
#: assets/views/cluster.py:
102 assets/views/group.py:34
#: assets/views/group.py:
52 assets/views/group.py:69 assets/views/group.py:87
#: assets/views/system_user.py:2
8 assets/views/system_user.py:44
#: assets/views/system_user.py:
60 assets/views/system_user.py:75
#: templates/_nav.html:19
msgid "Assets"
msgstr "资产管理"
...
...
@@ -524,11 +588,6 @@ msgstr "资产管理"
msgid "Select Asset"
msgstr "选择资产"
#: assets/templates/assets/_asset_group_bulk_update_modal.html:22
#: assets/templates/assets/cluster_list.html:22
msgid "System users"
msgstr "系统用户"
#: assets/templates/assets/_asset_group_bulk_update_modal.html:24
msgid "Select System Users"
msgstr "选择系统用户"
...
...
@@ -561,7 +620,7 @@ msgstr "如果设置了id,则会使用该行信息更新该id的资产"
#: assets/templates/assets/_system_user.html:16
#: assets/templates/assets/system_user_list.html:16
#: assets/views/system_user.py:4
9
#: assets/views/system_user.py:4
5
msgid "Create system user"
msgstr "创建系统用户"
...
...
@@ -588,7 +647,7 @@ msgstr "自动生成秘钥"
#: assets/templates/assets/_system_user.html:65
#: assets/templates/assets/asset_create.html:32
#: assets/templates/assets/asset_update.html:47
#: assets/templates/assets/cluster_create_update.html:4
5
#: assets/templates/assets/cluster_create_update.html:4
6
#: perms/templates/perms/asset_permission_create_update.html:45
#: terminal/templates/terminal/terminal_update.html:40
msgid "Other"
...
...
@@ -598,8 +657,9 @@ msgstr "其它"
#: assets/templates/assets/admin_user_create_update.html:45
#: assets/templates/assets/asset_bulk_update.html:23
#: assets/templates/assets/asset_create.html:40
#: assets/templates/assets/asset_update.html:56
#: assets/templates/assets/cluster_create_update.html:53
#: assets/templates/assets/asset_group_create.html:16
#: assets/templates/assets/asset_update.html:55
#: assets/templates/assets/cluster_create_update.html:54
#: perms/templates/perms/asset_permission_create_update.html:67
#: terminal/templates/terminal/terminal_update.html:45
#: users/templates/users/_user.html:49
...
...
@@ -616,9 +676,10 @@ msgstr "重置"
#: assets/templates/assets/admin_user_create_update.html:46
#: assets/templates/assets/asset_bulk_update.html:24
#: assets/templates/assets/asset_create.html:41
#: assets/templates/assets/asset_group_create.html:17
#: assets/templates/assets/asset_list.html:55
#: assets/templates/assets/asset_update.html:5
7
#: assets/templates/assets/cluster_create_update.html:5
4
#: assets/templates/assets/asset_update.html:5
6
#: assets/templates/assets/cluster_create_update.html:5
5
#: perms/templates/perms/asset_permission_create_update.html:68
#: terminal/templates/terminal/terminal_update.html:46
#: users/templates/users/_user.html:50
...
...
@@ -652,6 +713,52 @@ msgstr "详情"
msgid "Assets list"
msgstr "资产列表"
#: assets/templates/assets/admin_user_assets.html:24
#: assets/templates/assets/admin_user_detail.html:24
#: assets/templates/assets/admin_user_list.html:83
#: assets/templates/assets/asset_detail.html:24
#: assets/templates/assets/asset_group_detail.html:18
#: assets/templates/assets/asset_group_detail.html:172
#: assets/templates/assets/asset_group_list.html:42
#: assets/templates/assets/asset_list.html:95
#: assets/templates/assets/cluster_assets.html:170
#: assets/templates/assets/cluster_detail.html:25
#: assets/templates/assets/cluster_list.html:43
#: assets/templates/assets/system_user_asset.html:25
#: assets/templates/assets/system_user_detail.html:26
#: assets/templates/assets/system_user_list.html:84
#: perms/templates/perms/asset_permission_detail.html:30
#: perms/templates/perms/asset_permission_list.html:73
#: terminal/templates/terminal/terminal_detail.html:16
#: terminal/templates/terminal/terminal_list.html:71
#: users/templates/users/user_detail.html:25
#: users/templates/users/user_group_detail.html:28
#: users/templates/users/user_group_list.html:39
#: users/templates/users/user_list.html:76
msgid "Update"
msgstr "更新"
#: assets/templates/assets/admin_user_assets.html:28
#: assets/templates/assets/admin_user_detail.html:28
#: assets/templates/assets/admin_user_list.html:84
#: assets/templates/assets/asset_detail.html:28
#: assets/templates/assets/asset_group_list.html:43
#: assets/templates/assets/asset_list.html:96
#: assets/templates/assets/cluster_detail.html:29
#: assets/templates/assets/cluster_list.html:44
#: assets/templates/assets/system_user_list.html:85
#: ops/templates/ops/task_list.html:71
#: perms/templates/perms/asset_permission_detail.html:34
#: perms/templates/perms/asset_permission_list.html:74
#: terminal/templates/terminal/terminal_list.html:73
#: users/templates/users/user_detail.html:29
#: users/templates/users/user_group_detail.html:32
#: users/templates/users/user_group_list.html:41
#: users/templates/users/user_list.html:80
#: users/templates/users/user_list.html:84
msgid "Delete"
msgstr "删除"
#: assets/templates/assets/admin_user_assets.html:37
#: assets/templates/assets/asset_group_detail.html:26
#: perms/templates/perms/asset_permission_asset.html:35
...
...
@@ -668,11 +775,13 @@ msgid "Type"
msgstr "类型"
#: assets/templates/assets/admin_user_assets.html:63
#: assets/templates/assets/asset_group_detail.html:49
#: assets/templates/assets/cluster_assets.html:55
#: terminal/templates/terminal/terminal_list.html:35
msgid "Alive"
msgstr "在线"
#: assets/templates/assets/admin_user_list.html:25
#: assets/templates/assets/asset_detail.html:376
#: assets/templates/assets/asset_list.html:38
#: assets/templates/assets/system_user_asset.html:55
#: assets/templates/assets/system_user_list.html:27
msgid "Reachable"
msgstr "可连接"
#: assets/templates/assets/admin_user_assets.html:75
#: assets/templates/assets/cluster_assets.html:68
...
...
@@ -699,7 +808,7 @@ msgstr "任务已下发,查看左侧资产状态"
#: assets/templates/assets/admin_user_create_update.html:16
#: assets/templates/assets/admin_user_list.html:14
#: assets/views/admin_user.py:4
5
#: assets/views/admin_user.py:4
8
msgid "Create admin user"
msgstr "创建管理用户"
...
...
@@ -709,7 +818,7 @@ msgstr "使用集群管理用户"
#: assets/templates/assets/admin_user_detail.html:101
#: assets/templates/assets/asset_detail.html:230
#: assets/templates/assets/asset_group_list.html:8
7
#: assets/templates/assets/asset_group_list.html:8
5
#: assets/templates/assets/asset_list.html:202
#: assets/templates/assets/cluster_assets.html:104
#: assets/templates/assets/cluster_list.html:89
...
...
@@ -719,25 +828,26 @@ msgstr "使用集群管理用户"
#: users/templates/users/user_detail.html:338
#: users/templates/users/user_detail.html:363
#: users/templates/users/user_detail.html:386
#: users/templates/users/user_group_create_update.html:
46
#: users/templates/users/user_group_create_update.html:
32
#: users/templates/users/user_group_list.html:82
#: users/templates/users/user_list.html:184
#: users/templates/users/user_profile.html:181
msgid "Confirm"
msgstr "确认"
#: assets/templates/assets/admin_user_list.html:24
#: assets/templates/assets/cluster_list.html:21
#: users/templates/users/_select_user_modal.html:17
msgid "Asset num"
msgstr "资产数量"
#: assets/templates/assets/admin_user_list.html:25
#: assets/templates/assets/admin_user_list.html:26
#: assets/templates/assets/system_user_list.html:28
msgid "Unreachable"
msgstr "不可达"
#: assets/templates/assets/admin_user_list.html:27
#: assets/templates/assets/system_user_list.html:29
#: ops/templates/ops/adhoc_history.html:54
#: ops/templates/ops/task_history.html:57
msgid "Ratio"
msgstr "比例"
#: assets/templates/assets/admin_user_list.html:29
#: assets/templates/assets/asset_group_detail.html:50
#: assets/templates/assets/asset_group_list.html:18
#: assets/templates/assets/asset_list.html:39
...
...
@@ -746,50 +856,22 @@ msgstr "不可达"
#: assets/templates/assets/system_user_list.html:31
#: assets/templates/assets/user_asset_list.html:27
#: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:61
#: ops/templates/ops/task_history.html:62 ops/templates/ops/task_list.html:4
6
#: ops/templates/ops/task_history.html:62 ops/templates/ops/task_list.html:4
1
#: perms/templates/perms/asset_permission_list.html:32
#: terminal/templates/terminal/session_list.html:7
8
#: terminal/templates/terminal/session_list.html:7
9
#: terminal/templates/terminal/terminal_list.html:36
#: users/templates/users/user_group_list.html:15
#: users/templates/users/user_list.html:28
msgid "Action"
msgstr "动作"
#: assets/templates/assets/admin_user_list.html:47
#: assets/templates/assets/asset_group_detail.html:172
#: assets/templates/assets/asset_group_list.html:42
#: assets/templates/assets/asset_list.html:95
#: assets/templates/assets/cluster_assets.html:170
#: assets/templates/assets/cluster_list.html:43
#: assets/templates/assets/system_user_list.html:84
#: perms/templates/perms/asset_permission_list.html:73
#: terminal/templates/terminal/terminal_list.html:71
#: users/templates/users/user_group_list.html:39
#: users/templates/users/user_list.html:76
msgid "Update"
msgstr "更新"
#: assets/templates/assets/admin_user_list.html:48
#: assets/templates/assets/asset_group_list.html:43
#: assets/templates/assets/asset_list.html:96
#: assets/templates/assets/cluster_list.html:44
#: assets/templates/assets/system_user_list.html:85
#: ops/templates/ops/task_list.html:76
#: perms/templates/perms/asset_permission_list.html:74
#: terminal/templates/terminal/terminal_list.html:73
#: users/templates/users/user_group_list.html:41
#: users/templates/users/user_list.html:80
#: users/templates/users/user_list.html:84
msgid "Delete"
msgstr "删除"
#: assets/templates/assets/asset_create.html:28
#: assets/templates/assets/asset_update.html:33
msgid "Group"
msgstr "组"
#: assets/templates/assets/asset_detail.html:20 assets/views/asset.py:18
0
#: assets/views/cluster.py:
98
#: assets/templates/assets/asset_detail.html:20 assets/views/asset.py:18
6
#: assets/views/cluster.py:
103
msgid "Asset detail"
msgstr "资产详情"
...
...
@@ -822,6 +904,7 @@ msgstr "快速修改"
#: assets/templates/assets/asset_list.html:37
#: assets/templates/assets/user_asset_list.html:25 perms/models.py:20
#: perms/templates/perms/asset_permission_create_update.html:47
#: perms/templates/perms/asset_permission_detail.html:116
#: terminal/templates/terminal/terminal_list.html:34
#: users/templates/users/_select_user_modal.html:18
#: users/templates/users/user_detail.html:127
...
...
@@ -847,26 +930,25 @@ msgstr "添加到资产组"
msgid "Update successfully!"
msgstr "更新成功"
#: assets/templates/assets/asset_detail.html:376
#: assets/templates/assets/asset_list.html:38
#: assets/templates/assets/system_user_asset.html:55
#: assets/templates/assets/system_user_list.html:27
msgid "Reachable"
msgstr "可连接"
#: assets/templates/assets/asset_group_detail.html:16
msgid "Group assets"
msgstr "组下资产"
#: assets/templates/assets/asset_group_detail.html:49
#: assets/templates/assets/cluster_assets.html:55
#: terminal/templates/terminal/terminal_list.html:35
msgid "Alive"
msgstr "在线"
#: assets/templates/assets/asset_group_detail.html:62
msgid "Add assets to this group"
msgstr "添加资产到该组"
#: assets/templates/assets/asset_group_detail.html:79
#: perms/templates/perms/asset_permission_asset.html:
108
#: perms/templates/perms/asset_permission_asset.html:
97
#: perms/templates/perms/asset_permission_detail.html:153
#: perms/templates/perms/asset_permission_user.html:
108
#: perms/templates/perms/asset_permission_user.html:1
36
#: perms/templates/perms/asset_permission_user.html:
97
#: perms/templates/perms/asset_permission_user.html:1
25
#: users/templates/users/user_group_detail.html:95
msgid "Add"
msgstr "添加"
...
...
@@ -875,12 +957,12 @@ msgstr "添加"
msgid "Remove"
msgstr "移除"
#: assets/templates/assets/asset_group_list.html:7 assets/views/group.py:3
1
#: assets/views/group.py:
94
#: assets/templates/assets/asset_group_list.html:7 assets/views/group.py:3
5
#: assets/views/group.py:
88
msgid "Create asset group"
msgstr "创建资产组"
#: assets/templates/assets/asset_group_list.html:8
2
#: assets/templates/assets/asset_group_list.html:8
0
#: assets/templates/assets/asset_list.html:197
#: assets/templates/assets/cluster_list.html:84
#: assets/templates/assets/system_user_list.html:129
...
...
@@ -891,29 +973,29 @@ msgstr "创建资产组"
msgid "Are you sure?"
msgstr "你确认吗?"
#: assets/templates/assets/asset_group_list.html:8
3
#: assets/templates/assets/asset_group_list.html:8
1
#: users/templates/users/user_group_list.html:78
msgid "This will delete the selected groups !!!"
msgstr "删除选择组"
#: assets/templates/assets/asset_group_list.html:
91
#: assets/templates/assets/asset_group_list.html:
89
msgid "Group deleted"
msgstr "组已被删除"
#: assets/templates/assets/asset_group_list.html:9
2
#: assets/templates/assets/asset_group_list.html:9
7
#: assets/templates/assets/asset_group_list.html:9
0
#: assets/templates/assets/asset_group_list.html:9
5
msgid "Group Delete"
msgstr "删除"
#: assets/templates/assets/asset_group_list.html:9
6
#: assets/templates/assets/asset_group_list.html:9
4
msgid "Group deleting failed."
msgstr "删除失败"
#: assets/templates/assets/asset_group_list.html:15
9
#: assets/templates/assets/asset_group_list.html:15
7
msgid "The selected asset groups has been updated successfully."
msgstr "更新成功"
#: assets/templates/assets/asset_group_list.html:1
60
#: assets/templates/assets/asset_group_list.html:1
58
msgid "AssetGroup Updated"
msgstr "资产组更新"
...
...
@@ -1000,7 +1082,7 @@ msgid "Test assets connective"
msgstr "测试资产可连接性"
#: assets/templates/assets/cluster_assets.html:77
#: ops/templates/ops/task_list.html:7
5
#: ops/templates/ops/task_list.html:7
0
msgid "Run"
msgstr "执行"
...
...
@@ -1012,14 +1094,20 @@ msgstr "添加资产到"
msgid "Select asset"
msgstr "选择资产"
#: assets/templates/assets/cluster_assets.html:211
#: assets/templates/assets/system_user_asset.html:162
msgid "Task has been send, seen left assets status"
msgstr "任务已下发,查看左侧资产状态"
#: assets/templates/assets/cluster_create_update.html:41
#: users/templates/users/user_profile.html:20
msgid "Settings"
msgstr "设置"
#: assets/templates/assets/cluster_list.html:11 assets/views/cluster.py:39
msgid "Create Cluster"
msgstr "创建Cluster"
#: assets/templates/assets/cluster_list.html:21
#: users/templates/users/_select_user_modal.html:17
msgid "Asset num"
msgstr "资产数量"
#: assets/templates/assets/cluster_list.html:85
msgid "This will delete the selected cluster"
...
...
@@ -1064,10 +1152,6 @@ msgstr "推送"
msgid "Task has been send, Go to ops task list seen result"
msgstr "任务已下发,查看ops任务列表"
#: assets/templates/assets/system_user_asset.html:162
msgid "Task has been send, seen left assets status"
msgstr "任务已下发,查看左侧资产状态"
#: assets/templates/assets/system_user_detail.html:22
msgid "Attached assets"
msgstr "关联的资产"
...
...
@@ -1088,12 +1172,6 @@ msgstr "集群"
msgid "Add to cluster"
msgstr "添加到集群"
#: assets/templates/assets/system_user_list.html:29
#: ops/templates/ops/adhoc_history.html:54
#: ops/templates/ops/task_history.html:57
msgid "Ratio"
msgstr "比例"
#: assets/templates/assets/system_user_list.html:130
msgid "This will delete the selected System Users !!!"
msgstr "删除选择系统用户"
...
...
@@ -1115,84 +1193,93 @@ msgstr "系统用户删除失败"
msgid "Connective"
msgstr "连接性"
#: assets/templates/assets/user_asset_list.html:6
6
#: assets/templates/assets/user_asset_list.html:6
5
msgid "Connect"
msgstr "连接"
#: assets/views/admin_user.py:
28
#: assets/views/admin_user.py:
30
msgid "Admin user list"
msgstr "管理用户列表"
#: assets/views/admin_user.py:52
#, python-brace-format
msgid "Create admin user <a href=\"{url}\">{name}</a> successfully."
msgstr "创建管理用户 <a href=\"{url}\">{name}</a> 成功"
#: assets/views/admin_user.py:68
#: assets/views/admin_user.py:64
msgid "Update admin user"
msgstr "更新管理用户"
#: assets/views/admin_user.py:8
9 assets/views/admin_user.py:116
#: assets/views/admin_user.py:8
0 assets/views/admin_user.py:107
msgid "Admin user detail"
msgstr "管理用户详情"
#: assets/views/asset.py:4
8
assets/views/asset.py:62
#: assets/views/asset.py:4
9
assets/views/asset.py:62
msgid "Asset list"
msgstr "资产列表"
#: assets/views/asset.py:14
2
#: assets/views/asset.py:14
5
msgid "Bulk update asset"
msgstr "批量更新资产"
#: assets/views/asset.py:1
59
#: assets/views/asset.py:1
62
msgid "Update asset"
msgstr "编辑资产"
#: assets/views/asset.py:29
2
#: assets/views/asset.py:29
8
msgid "already exists"
msgstr "已经存在"
#: assets/views/cluster.py:2
3
#: assets/views/cluster.py:2
7
msgid "Cluster list"
msgstr "集群列表"
#: assets/views/cluster.py:38 assets/views/cluster.py:65
#: assets/views/cluster.py:42 assets/views/cluster.py:70
#: assets/views/system_user.py:96
msgid "assets"
msgstr "资产管理"
#: assets/views/cluster.py:66
#: assets/views/cluster.py:43
msgid "Create cluster"
msgstr "创建集群"
#: assets/views/cluster.py:71
msgid "Update Cluster"
msgstr "更新Cluster"
#: assets/views/cluster.py:8
1
#: assets/views/cluster.py:8
6
msgid "Cluster detail"
msgstr "集群详情"
#: assets/views/group.py:5
4
#: assets/views/group.py:5
3
msgid "Asset group list"
msgstr "资产组列表"
#: assets/views/group.py:7
2
#: assets/views/group.py:7
0
msgid "Asset group detail"
msgstr "资产组详情"
#: assets/views/system_user.py:
30
#: assets/views/system_user.py:
29
msgid "System user list"
msgstr "系统用户列表"
#: assets/views/system_user.py:57
#, python-brace-format
msgid "Create system user <a href=\"{url}\">{name}</a> successfully."
msgstr "创建系统用户 <a href=\"{url}\">{name}</a> 成功"
#: assets/views/system_user.py:72
#: assets/views/system_user.py:61
msgid "Update system user"
msgstr "更新系统用户"
#: assets/views/system_user.py:
92
#: assets/views/system_user.py:
76
msgid "System user detail"
msgstr "系统用户详情"
#: assets/views/system_user.py:97
msgid "System user asset"
msgstr "系统用户集群资产"
#: common/const.py:6
#, python-format
msgid "<b>%(name)s</b> was created successfully"
msgstr "<b>%(name)s</b> 创建成功"
#: common/const.py:7
#, python-format
msgid "<b>%(name)s</b> was updated successfully"
msgstr "<b>%(name)s</b> 更新成功"
#: common/mixins.py:29
msgid "is discard"
msgstr ""
...
...
@@ -1235,7 +1322,7 @@ msgid "Options"
msgstr "选项"
#: ops/models.py:152 ops/templates/ops/adhoc_detail.html:53
#: ops/templates/ops/task_adhoc.html:56 ops/templates/ops/task_list.html:
42
#: ops/templates/ops/task_adhoc.html:56 ops/templates/ops/task_list.html:
37
msgid "Hosts"
msgstr "主机"
...
...
@@ -1257,36 +1344,36 @@ msgstr "Become"
msgid "Create by"
msgstr "创建者"
#: ops/models.py:30
6
#: ops/models.py:30
7
msgid "Start time"
msgstr "开始时间"
#: ops/models.py:30
7
#: ops/models.py:30
8
msgid "End time"
msgstr "完成时间"
#: ops/models.py:30
8
ops/templates/ops/adhoc_history.html:57
#: ops/templates/ops/task_history.html:60 ops/templates/ops/task_list.html:4
5
#: ops/models.py:30
9
ops/templates/ops/adhoc_history.html:57
#: ops/templates/ops/task_history.html:60 ops/templates/ops/task_list.html:4
0
msgid "Time"
msgstr "时间"
#: ops/models.py:3
09
ops/templates/ops/adhoc_detail.html:106
#: ops/models.py:3
10
ops/templates/ops/adhoc_detail.html:106
#: ops/templates/ops/adhoc_history.html:55
#: ops/templates/ops/adhoc_history_detail.html:66
#: ops/templates/ops/task_detail.html:80 ops/templates/ops/task_history.html:58
msgid "Is finished"
msgstr "是否完成"
#: ops/models.py:31
0
ops/templates/ops/adhoc_history.html:56
#: ops/models.py:31
1
ops/templates/ops/adhoc_history.html:56
#: ops/templates/ops/task_history.html:59
msgid "Is success"
msgstr "是否成功"
#: ops/models.py:31
1
#: ops/models.py:31
2
msgid "Adhoc raw result"
msgstr "结果"
#: ops/models.py:31
2
#: ops/models.py:31
3
msgid "Adhoc result summary"
msgstr "汇总"
...
...
@@ -1296,7 +1383,7 @@ msgid "Version detail"
msgstr "版本详情"
#: ops/templates/ops/adhoc_detail.html:22
#: ops/templates/ops/adhoc_history.html:22 ops/views.py:1
20
#: ops/templates/ops/adhoc_history.html:22 ops/views.py:1
05
msgid "Version run history"
msgstr "执行历史"
...
...
@@ -1308,7 +1395,7 @@ msgstr "执行历史"
msgid "ID"
msgstr "ID"
#: ops/templates/ops/adhoc_detail.html:94 ops/templates/ops/task_list.html:
40
#: ops/templates/ops/adhoc_detail.html:94 ops/templates/ops/task_list.html:
35
msgid "Run times"
msgstr "执行次数"
...
...
@@ -1352,8 +1439,8 @@ msgstr "执行历史"
#: ops/templates/ops/adhoc_history.html:52
#: ops/templates/ops/adhoc_history_detail.html:58
#: ops/templates/ops/task_history.html:55 terminal/models.py:10
0
#: terminal/templates/terminal/session_list.html:7
6
#: ops/templates/ops/task_history.html:55 terminal/models.py:10
1
#: terminal/templates/terminal/session_list.html:7
7
msgid "Date start"
msgstr "开始日期"
...
...
@@ -1368,7 +1455,7 @@ msgstr "失败/成功/总"
msgid "Version"
msgstr "版本"
#: ops/templates/ops/adhoc_history_detail.html:19 ops/views.py:1
33
#: ops/templates/ops/adhoc_history_detail.html:19 ops/views.py:1
18
msgid "Run history detail"
msgstr "执行历史详情"
...
...
@@ -1394,12 +1481,12 @@ msgid "Success assets"
msgstr "成功资产"
#: ops/templates/ops/task_adhoc.html:19 ops/templates/ops/task_detail.html:19
#: ops/templates/ops/task_history.html:19 ops/views.py:5
8
#: ops/templates/ops/task_history.html:19 ops/views.py:5
3
msgid "Task detail"
msgstr "任务详情"
#: ops/templates/ops/task_adhoc.html:22 ops/templates/ops/task_detail.html:22
#: ops/templates/ops/task_history.html:22 ops/views.py:
71
#: ops/templates/ops/task_history.html:22 ops/views.py:
66
msgid "Task versions"
msgstr "任务各版本"
...
...
@@ -1414,6 +1501,7 @@ msgstr "版本"
#: ops/templates/ops/task_adhoc.html:60
#: terminal/templates/terminal/command_list.html:76
#: terminal/templates/terminal/session_detail.html:50
msgid "Datetime"
msgstr "日期"
...
...
@@ -1429,7 +1517,7 @@ msgstr "最新版本"
msgid "Contents"
msgstr "内容"
#: ops/templates/ops/task_list.html:2
5 ops/templates/ops/task_list.html:30
#: ops/templates/ops/task_list.html:2
0 ops/templates/ops/task_list.html:25
#: templates/_base_list.html:43 templates/_header_bar.html:8
#: terminal/templates/terminal/command_list.html:60
#: users/templates/users/login_log_list.html:35
...
...
@@ -1437,73 +1525,74 @@ msgstr "内容"
msgid "Search"
msgstr "搜索"
#: ops/templates/ops/task_list.html:
41
#: ops/templates/ops/task_list.html:
36
msgid "Versions"
msgstr "版本"
#: ops/templates/ops/task_list.html:
43
#: ops/templates/ops/task_list.html:
38
msgid "Success"
msgstr "成功"
#: ops/templates/ops/task_list.html:
44
#: ops/templates/ops/task_list.html:
39
#: users/templates/users/login_log_list.html:54
msgid "Date"
msgstr "日期"
#: ops/views.py:41 ops/views.py:57 ops/views.py:70 ops/views.py:83
#: ops/views.py:106 ops/views.py:119 ops/views.py:132
#: ops/templates/ops/task_list.html:125
msgid "Task start: "
msgstr "任务开始: "
#: ops/views.py:36 ops/views.py:52 ops/views.py:65 ops/views.py:78
#: ops/views.py:91 ops/views.py:104 ops/views.py:117
msgid "Ops"
msgstr "作业中心"
#: ops/views.py:
42
#: ops/views.py:
37
msgid "Task list"
msgstr "任务列表"
#: ops/views.py:
84
#: ops/views.py:
79
msgid "Task run history"
msgstr "执行历史"
#: perms/forms.py:16 users/forms.py:144 users/forms.py:149 users/forms.py:161
#: users/forms.py:19
0
#: users/forms.py:19
1
msgid "Select users"
msgstr "选择用户"
#: perms/forms.py:18 perms/models.py:15
#: perms/templates/perms/asset_permission_create_update.html:36
#: perms/templates/perms/asset_permission_list.html:26 templates/_nav.html:12
#: te
mplates/_user_profile.html:14 terminal/backends/command/models.py:10
#: terminal/
models.py:92 terminal/
templates/terminal/command_list.html:32
#: te
rminal/backends/command/models.py:10 terminal/models.py:92
#: terminal/templates/terminal/command_list.html:32
#: terminal/templates/terminal/command_list.html:72
#: terminal/templates/terminal/session_list.html:33
#: terminal/templates/terminal/session_list.html:71 users/models/user.py:31
#: users/templates/users/user_group_detail.html:78 users/views/user.py:348
#: terminal/templates/terminal/session_list.html:71 users/forms.py:187
#: users/models/user.py:31 users/templates/users/user_group_detail.html:78
#: users/views/user.py:338
msgid "User"
msgstr "用户"
#: perms/forms.py:3
0 perms/templates/perms/asset_permission_user.html:127
#: perms/forms.py:3
1 perms/templates/perms/asset_permission_user.html:116
msgid "Select user groups"
msgstr "选择用户组"
#: perms/forms.py:39 perms/templates/perms/asset_permission_detail.html:144
#: users/forms.py:243
msgid "Select system users"
msgstr "选择系统用户"
#: perms/forms.py:44
msgid "User or user group at least one required"
msgstr ""
#: perms/forms.py:52
msgid "User or group at least one required"
msgstr "用户和组至少需要选一个"
#: perms/forms.py:
45
msgid "Asset or
Asset
group at least one required"
msgstr ""
#: perms/forms.py:
60
msgid "Asset or group at least one required"
msgstr "
资产或组至少需要选择一个
"
#: perms/forms.py:
59
msgid "Asset {} not have [{}] system users, please check \n"
msgstr ""
#: perms/forms.py:
78
msgid "Asset {}
of cluster {}
not have [{}] system users, please check \n"
msgstr "
资产 {} 所在集群 {} 不包含系统用户 [{}] 请检查\n
"
#: perms/forms.py:67
msgid "Asset {}: {} not have [{}] system users, please check"
msgstr ""
#: perms/forms.py:87
msgid ""
"Asset {}(group {}) of cluster {} not have [{}] system users, please check \n"
msgstr "资产 {}(组 {}) 所在集群 {} 不包含系统用户 [{}] 请检查\n"
#: perms/models.py:16 perms/templates/perms/asset_permission_list.html:27
#: templates/_nav.html:13 users/models/user.py:38
...
...
@@ -1513,23 +1602,6 @@ msgstr ""
msgid "User group"
msgstr "用户组"
#: perms/models.py:18 perms/templates/perms/asset_permission_list.html:29
#: templates/_nav.html:23
msgid "Asset group"
msgstr "资产组"
#: perms/models.py:19 perms/templates/perms/asset_permission_detail.html:136
#: perms/templates/perms/asset_permission_list.html:30 templates/_nav.html:26
#: terminal/backends/command/models.py:12 terminal/models.py:94
#: terminal/templates/terminal/command_list.html:48
#: terminal/templates/terminal/command_list.html:74
#: terminal/templates/terminal/session_list.html:49
#: terminal/templates/terminal/session_list.html:73
#: users/templates/users/user_granted_asset.html:50
#: users/templates/users/user_group_granted_asset.html:52
msgid "System user"
msgstr "系统用户"
#: perms/models.py:21 perms/templates/perms/asset_permission_detail.html:86
#: users/models/user.py:50 users/templates/users/user_detail.html:94
#: users/templates/users/user_profile.html:96
...
...
@@ -1548,21 +1620,15 @@ msgstr "用户或用户组"
msgid "Assets and asset groups"
msgstr "资产或资产组"
#: perms/templates/perms/asset_permission_asset.html:57
#: perms/templates/perms/asset_permission_list.html:31
#: perms/templates/perms/asset_permission_user.html:57
msgid "Is valid"
msgstr "有效"
#: perms/templates/perms/asset_permission_asset.html:91
#: perms/templates/perms/asset_permission_asset.html:80
msgid "Add asset to this permission"
msgstr "添加资产"
#: perms/templates/perms/asset_permission_asset.html:1
19
#: perms/templates/perms/asset_permission_asset.html:1
08
msgid "Add asset group to this permission"
msgstr "添加资产组"
#: perms/templates/perms/asset_permission_asset.html:1
36
#: perms/templates/perms/asset_permission_asset.html:1
25
#: users/templates/users/user_detail.html:195
msgid "Join"
msgstr "加入"
...
...
@@ -1596,70 +1662,53 @@ msgstr "系统用户数量"
msgid "Create permission"
msgstr "创建授权规则"
#: perms/templates/perms/asset_permission_list.html:31
msgid "Is valid"
msgstr "有效"
#: perms/templates/perms/asset_permission_user.html:35
msgid "User list of "
msgstr "用户列表"
#: perms/templates/perms/asset_permission_user.html:56 users/models/user.py:37
#: users/templates/users/user_detail.html:70
#: users/templates/users/user_profile.html:59
msgid "Email"
msgstr "邮件"
#: perms/templates/perms/asset_permission_user.html:91
#: perms/templates/perms/asset_permission_user.html:80
msgid "Add user to asset permission"
msgstr "添加用户"
#: perms/templates/perms/asset_permission_user.html:
99
#: perms/templates/perms/asset_permission_user.html:
88
#: users/templates/users/login_log_list.html:28
msgid "Select user"
msgstr "选择用户"
#: perms/templates/perms/asset_permission_user.html:1
19
#: perms/templates/perms/asset_permission_user.html:1
08
msgid "Add user group to asset permission"
msgstr "添加用户组"
#: perms/views.py:2
7 perms/views.py:77 perms/views.py:103 perms/views.py:128
#: perms/views.py:1
65 perms/views.py:195
templates/_nav.html:30
#: perms/views.py:2
8 perms/views.py:44 perms/views.py:60 perms/views.py:74
#: perms/views.py:1
11 perms/views.py:141
templates/_nav.html:30
msgid "Perms"
msgstr "权限管理"
#: perms/views.py:2
8
#: perms/views.py:2
9
msgid "Asset permission list"
msgstr "资产授权列表"
#: perms/views.py:63
#, python-brace-format
msgid "Create asset permission <a href=\"{url}\"> {name} </a> successfully."
msgstr "创建授权 <a href=\"{url}\"> {name} </a> 成功"
#: perms/views.py:78
#: perms/views.py:45
msgid "Create asset permission"
msgstr "创建权限规则"
#: perms/views.py:89
#, python-brace-format
msgid "Create asset permission <a href=\"{url}\"> {name} </a> success."
msgstr "创建授权 <a href=\"{url}\"> {name} </a> 成功"
#: perms/views.py:104
#: perms/views.py:61
msgid "Update asset permission"
msgstr "更新资产授权"
#: perms/views.py:115
#, python-brace-format
msgid "Update asset permission <a href=\"{url}\"> {name} </a> success."
msgstr "更新授权 <a href=\"{url}\"> {name} </a> 成功"
#: perms/views.py:129
#: perms/views.py:75
msgid "Asset permission detail"
msgstr "资产授权详情"
#: perms/views.py:1
66
#: perms/views.py:1
12
msgid "Asset permission user list"
msgstr "资产授权包含用户"
#: perms/views.py:1
96
#: perms/views.py:1
42
msgid "Asset permission asset list"
msgstr "资产组授权包含资产"
...
...
@@ -1671,16 +1720,34 @@ msgstr "欢迎使用Jumpserver开源跳板机系统"
msgid "Help"
msgstr "帮助"
#: templates/_header_bar.html:24 templates/_user_profile.html:29
#: templates/_header_bar.html:33 templates/_nav_user.html:9
#: users/templates/users/_user.html:42
#: users/templates/users/user_password_update.html:37
#: users/templates/users/user_profile.html:17
#: users/templates/users/user_profile_update.html:37
#: users/templates/users/user_profile_update.html:57
#: users/templates/users/user_pubkey_update.html:37 users/views/user.py:320
msgid "Profile"
msgstr "个人信息"
#: templates/_header_bar.html:37
msgid "Admin page"
msgstr "管理页面"
#: templates/_header_bar.html:39
msgid "User page"
msgstr "用户页面"
#: templates/_header_bar.html:42
msgid "Logout"
msgstr "注销登录"
#: templates/_header_bar.html:
28
users/templates/users/login.html:42
#: templates/_header_bar.html:
46
users/templates/users/login.html:42
#: users/templates/users/login.html:61
msgid "Login"
msgstr "登录"
#: templates/_header_bar.html:
41
templates/_nav.html:4
#: templates/_header_bar.html:
59
templates/_nav.html:4
msgid "Dashboard"
msgstr "仪表盘"
...
...
@@ -1714,11 +1781,11 @@ msgstr ""
msgid "Close"
msgstr "关闭"
#: templates/_nav.html:9 users/views/group.py:
30 users/views/group.py:46
#: users/views/group.py:
72 users/views/group.py:89 users/views/login.py:192
#: users/views/login.py:24
1 users/views/user.py:55 users/views/user.py:70
#: users/views/user.py:9
5 users/views/user.py:151 users/views/user.py:308
#: users/views/user.py:3
22 users/views/user.py:366 users/views/user.py:38
8
#: templates/_nav.html:9 users/views/group.py:
28 users/views/group.py:44
#: users/views/group.py:
62 users/views/group.py:79 users/views/login.py:193
#: users/views/login.py:24
2 users/views/user.py:57 users/views/user.py:72
#: users/views/user.py:9
2 users/views/user.py:148 users/views/user.py:305
#: users/views/user.py:3
19 users/views/user.py:356 users/views/user.py:37
8
msgid "Users"
msgstr "用户管理"
...
...
@@ -1739,11 +1806,11 @@ msgid "Task"
msgstr "任务"
#: templates/_nav.html:47 templates/_nav.html:50
#: terminal/templates/terminal/session_list.html:7
4
#: terminal/views/command.py:47 terminal/views/session.py:
54
#: terminal/views/session.py:
77 terminal/views/session.py:9
4
#: terminal/views/
session.py:116 terminal/views/terminal.py:31
#: terminal/views/terminal.py:
46 terminal/views/terminal.py:
58
#: terminal/templates/terminal/session_list.html:7
5
#: terminal/views/command.py:47 terminal/views/session.py:
75
#: terminal/views/session.py:
92 terminal/views/session.py:11
4
#: terminal/views/
terminal.py:31 terminal/views/terminal.py:46
#: terminal/views/terminal.py:58
msgid "Terminal"
msgstr "终端"
...
...
@@ -1755,43 +1822,18 @@ msgstr "在线会话"
msgid "Session offline"
msgstr "离线会话"
#: templates/_nav.html:53 terminal/models.py:9
8
#: templates/_nav.html:53 terminal/models.py:9
9
#: terminal/templates/terminal/command_list.html:55
#: terminal/templates/terminal/command_list.html:71
#: terminal/templates/terminal/session_list.html:75
#: terminal/templates/terminal/session_detail.html:48
#: terminal/templates/terminal/session_list.html:76
msgid "Command"
msgstr "命令"
#: templates/_nav.html:73
msgid "Visit us"
msgstr "访问官网"
#: templates/_nav_user.html:4
msgid "My assets"
msgstr "我的资产"
#: templates/_nav_user.html:9 templates/_user_profile.html:19
#: users/templates/users/_user.html:42
#: users/templates/users/user_password_update.html:37
#: users/templates/users/user_profile.html:17
#: users/templates/users/user_profile_update.html:37
#: users/templates/users/user_profile_update.html:57
#: users/templates/users/user_pubkey_update.html:37 users/views/user.py:323
msgid "Profile"
msgstr "个人信息"
#: templates/_user_profile.html:20
msgid "Profile settings"
msgstr "个人信息设置"
#: templates/_user_profile.html:24
msgid "Admin page"
msgstr "管理页面"
#: templates/_user_profile.html:26
msgid "User page"
msgstr "用户页面"
#: templates/captcha/image.html:3
msgid "Play CAPTCHA as audio file"
msgstr "语言播放验证码"
...
...
@@ -1818,16 +1860,12 @@ msgid "Session"
msgstr "会话"
#: terminal/forms.py:15
msgid "A unique addr of every terminal, user browser can arrive it"
msgstr ""
#: terminal/forms.py:16
msgid "Coco ssh listen port"
msgstr ""
msgstr "
SSH 监听端口
"
#: terminal/forms.py:1
7
#: terminal/forms.py:1
6
msgid "Coco http/ws listen port"
msgstr ""
msgstr "
Http/Websocket 监听端口
"
#: terminal/models.py:15
msgid "Remote Address"
...
...
@@ -1847,7 +1885,7 @@ msgstr "在线会话"
#: terminal/models.py:69
msgid "CPU Usage"
msgstr ""
msgstr "
CPU使用
"
#: terminal/models.py:70
msgid "Memory Used"
...
...
@@ -1855,34 +1893,39 @@ msgstr "内存使用"
#: terminal/models.py:71
msgid "Connections"
msgstr "连接"
msgstr "连接
数
"
#: terminal/models.py:72
msgid "Threads"
msgstr "线程"
msgstr "线程
数
"
#: terminal/models.py:73
msgid "Boot Time"
msgstr "运行时间"
#: terminal/models.py:97 terminal/templates/terminal/session_list.html:98
#: terminal/models.py:96 terminal/templates/terminal/session_list.html:74
#: terminal/templates/terminal/terminal_detail.html:47
msgid "Remote addr"
msgstr "远端地址"
#: terminal/models.py:98 terminal/templates/terminal/session_list.html:100
msgid "Replay"
msgstr "回放"
#: terminal/models.py:10
1
#: terminal/models.py:10
2
msgid "Date end"
msgstr "结束日期"
#: terminal/models.py:11
8
#: terminal/models.py:11
9
msgid "Args"
msgstr "参数"
#: terminal/templates/terminal/command_list.html:88
msgid "Goto"
msgstr ""
msgstr "
转到
"
#: terminal/templates/terminal/session_detail.html:17
#: terminal/views/session.py:11
7
#: terminal/views/session.py:11
5
msgid "Session detail"
msgstr "会话详情"
...
...
@@ -1912,19 +1955,19 @@ msgstr "监控"
msgid "Terminate session"
msgstr "终止会话"
#: terminal/templates/terminal/session_list.html:7
7
#: terminal/templates/terminal/session_list.html:7
8
msgid "Duration"
msgstr "时长"
#: terminal/templates/terminal/session_list.html:10
0
#: terminal/templates/terminal/session_list.html:10
2
msgid "Monitor"
msgstr "监控"
#: terminal/templates/terminal/session_list.html:10
1
#: terminal/templates/terminal/session_list.html:10
3
msgid "Terminate"
msgstr "终断"
#: terminal/templates/terminal/session_list.html:11
7
#: terminal/templates/terminal/session_list.html:11
9
msgid "Terminate task send, waiting ..."
msgstr "终断任务已发送,请等待"
...
...
@@ -1933,10 +1976,6 @@ msgstr "终断任务已发送,请等待"
msgid "Terminal detail"
msgstr "终端详情"
#: terminal/templates/terminal/terminal_detail.html:47
msgid "Remote address"
msgstr "远端地址"
#: terminal/templates/terminal/terminal_detail.html:51
#: terminal/templates/terminal/terminal_list.html:31
msgid "SSH port"
...
...
@@ -1971,14 +2010,14 @@ msgstr "接受终端注册"
msgid "Info"
msgstr "信息"
#: terminal/views/session.py:55 terminal/views/session.py:95
msgid "Session offline list"
msgstr "离线会话"
#: terminal/views/session.py:78
#: terminal/views/session.py:76
msgid "Session online list"
msgstr "在线会话"
#: terminal/views/session.py:93
msgid "Session offline list"
msgstr "离线会话"
#: terminal/views/terminal.py:32
msgid "Terminal list"
msgstr "终端列表"
...
...
@@ -2119,7 +2158,7 @@ msgstr "Agent"
msgid "Date login"
msgstr "登录日期"
#: users/models/user.py:30 users/models/user.py:25
5
#: users/models/user.py:30 users/models/user.py:25
9
msgid "Administrator"
msgstr "管理员"
...
...
@@ -2127,6 +2166,11 @@ msgstr "管理员"
msgid "Application"
msgstr "应用程序"
#: users/models/user.py:37 users/templates/users/user_detail.html:70
#: users/templates/users/user_profile.html:59
msgid "Email"
msgstr "邮件"
#: users/models/user.py:39 users/templates/users/_select_user_modal.html:15
#: users/templates/users/user_detail.html:86
#: users/templates/users/user_list.html:25
...
...
@@ -2146,10 +2190,6 @@ msgstr "微信"
msgid "Enable OTP"
msgstr "二次验证"
#: users/models/user.py:46
msgid "Private key"
msgstr "ssh私钥"
#: users/models/user.py:47 users/templates/users/user_password_update.html:43
#: users/templates/users/user_profile.html:71
#: users/templates/users/user_profile_update.html:43
...
...
@@ -2157,7 +2197,7 @@ msgstr "ssh私钥"
msgid "Public key"
msgstr "ssh公钥"
#: users/models/user.py:2
58
#: users/models/user.py:2
62
msgid "Administrator is the super user of system"
msgstr "Administrator是初始的超级管理员"
...
...
@@ -2259,7 +2299,7 @@ msgid "Setting"
msgstr "设置"
#: users/templates/users/user_create.html:4
#: users/templates/users/user_list.html:16 users/views/user.py:7
0
#: users/templates/users/user_list.html:16 users/views/user.py:7
2
msgid "Create user"
msgstr "创建用户"
...
...
@@ -2270,7 +2310,7 @@ msgstr "生成重置密码连接,通过邮件发送给用户"
#: users/templates/users/user_detail.html:19
#: users/templates/users/user_granted_asset.html:18
#: users/templates/users/user_group_granted_asset.html:18
#: users/views/user.py:1
52
#: users/views/user.py:1
49
msgid "User detail"
msgstr "用户详情"
...
...
@@ -2306,13 +2346,13 @@ msgstr "已发送邮件到用户邮箱"
msgid ""
"This will reset the user's password. A password-reset email will be sent to "
"the user\\'s mailbox."
msgstr ""
msgstr "
重设密码邮件将会发送到用户邮箱
"
#: users/templates/users/user_detail.html:348
msgid ""
"The reset-ssh-public-key E-mail has been sent successfully. Please inform "
"the user to update his new ssh public key."
msgstr ""
msgstr "
重设秘钥邮件将会发送到用户邮箱
"
#: users/templates/users/user_detail.html:349
#: users/templates/users/user_profile.html:144
...
...
@@ -2345,11 +2385,11 @@ msgstr "授权资产"
msgid "Asset groups granted of "
msgstr "授权资产组"
#: users/templates/users/user_group_create_update.html:
45
#: users/templates/users/user_group_create_update.html:
31
msgid "Cancel"
msgstr "取消"
#: users/templates/users/user_group_detail.html:22 users/views/group.py:
9
0
#: users/templates/users/user_group_detail.html:22 users/views/group.py:
8
0
msgid "User group detail"
msgstr "资产组详情"
...
...
@@ -2361,7 +2401,7 @@ msgstr "添加用户"
msgid "Valid"
msgstr "可用"
#: users/templates/users/user_group_list.html:5 users/views/group.py:4
7
#: users/templates/users/user_group_list.html:5 users/views/group.py:4
5
msgid "Create user group"
msgstr "创建用户组"
...
...
@@ -2399,8 +2439,8 @@ msgstr "用户删除失败"
msgid "OTP"
msgstr ""
#: users/templates/users/user_profile.html:100 users/views/user.py:1
81
#: users/views/user.py:23
3
#: users/templates/users/user_profile.html:100 users/views/user.py:1
78
#: users/views/user.py:23
0
msgid "User groups"
msgstr "用户组"
...
...
@@ -2424,7 +2464,7 @@ msgstr "指纹"
msgid "Update public key"
msgstr "更新密钥"
#: users/templates/users/user_update.html:4 users/views/user.py:9
5
#: users/templates/users/user_update.html:4 users/views/user.py:9
2
msgid "Update user"
msgstr "编辑用户"
...
...
@@ -2558,17 +2598,17 @@ msgstr "禁用或失效"
msgid "Password or SSH public key invalid"
msgstr "密码或秘钥不合法"
#: users/views/group.py:
31
#: users/views/group.py:
29
msgid "User group list"
msgstr "用户组列表"
#: users/views/group.py:
7
3
#: users/views/group.py:
6
3
msgid "Update user group"
msgstr "编辑用户组"
#: users/views/login.py:54
msgid "Please enable cookies and try again."
msgstr ""
msgstr "
设置你的浏览器支持cookie
"
#: users/views/login.py:83
msgid "Logout success"
...
...
@@ -2578,81 +2618,69 @@ msgstr "退出登录成功"
msgid "Logout success, return login page"
msgstr "退出登录成功,返回到登录页面"
#: users/views/login.py:
99
#: users/views/login.py:
100
msgid "Email address invalid, please input again"
msgstr "邮箱地址错误,重新输入"
#: users/views/login.py:11
2
#: users/views/login.py:11
3
msgid "Send reset password message"
msgstr "发送重置密码邮件"
#: users/views/login.py:11
3
#: users/views/login.py:11
4
msgid "Send reset password mail success, login your mail box and follow it "
msgstr ""
"发送重置邮件成功, 请登录邮箱查看, 按照提示操作 (如果没收到,请等待3-5分钟)"
#: users/views/login.py:12
7
#: users/views/login.py:12
8
msgid "Reset password success"
msgstr "重置密码成功"
#: users/views/login.py:12
8
#: users/views/login.py:12
9
msgid "Reset password success, return to login page"
msgstr "重置密码成功,返回到登录页面"
#: users/views/login.py:14
5 users/views/login.py:158
#: users/views/login.py:14
6 users/views/login.py:159
msgid "Token invalid or expired"
msgstr "Token错误或失效"
#: users/views/login.py:15
4
#: users/views/login.py:15
5
msgid "Password not same"
msgstr "密码不一致"
#: users/views/login.py:19
2
#: users/views/login.py:19
3
msgid "First login"
msgstr "首次登陆"
#: users/views/login.py:24
2
#: users/views/login.py:24
3
msgid "Login log list"
msgstr "登录日志"
#: users/views/user.py:5
6
#: users/views/user.py:5
8
msgid "User list"
msgstr "用户列表"
#: users/views/user.py:66 users/views/user.py:335
#, python-brace-format
msgid "Create user <a href=\"{url}\">{name}</a> successfully."
msgstr "创建用户 <a href=\"{url}\">{name}</a> 成功"
#: users/views/user.py:105
#: users/views/user.py:102
msgid "Bulk update user success"
msgstr "批量更新用户成功"
#: users/views/user.py:2
10
#: users/views/user.py:2
07
msgid "Invalid file."
msgstr "文件不合法"
#: users/views/user.py:30
9
#: users/views/user.py:30
6
msgid "User granted assets"
msgstr "用户授权资产"
#: users/views/user.py:3
4
9
#: users/views/user.py:3
3
9
msgid "Profile setting"
msgstr "个人信息设置"
#: users/views/user.py:3
6
7
#: users/views/user.py:3
5
7
msgid "Password update"
msgstr "密码更新"
#: users/views/user.py:3
8
9
#: users/views/user.py:3
7
9
msgid "Public key update"
msgstr "秘钥更新"
#~ msgid "Audits"
#~ msgstr "审计中心"
#~ msgid "Proxy log list"
#~ msgstr "Session列表"
#~ msgid "If also set private key, use that first"
#~ msgstr "如果设置私钥,则优先使用密钥"
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
...
...
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
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
):
...
...
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 %}
...
...
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 %}
...
...
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 %}
...
...
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 %}
...
...
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>
...
...
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 %}
...
...
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 %}
...
...
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
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'
...
...
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
:
...
...
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>
...
...
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 %}
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
);
}}
...
...
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"
);
...
...
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或其它认证查看自己授权的资产,资产组等
...
...
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'
...
...
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=/'
;
}
}
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 %}
...
...
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 %}
...
...
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' %}"
>
...
...
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>
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
):
...
...
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"
),
}
...
...
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"
))
...
...
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"
>
...
...
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>
...
...
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>
...
...
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 %}
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 %}
...
...
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
,
...
...
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
,
...
...
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
):
...
...
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
...
...
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>
...
...
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 %}
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
)
{
...
...
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"
>
...
...
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>
...
...
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
()
...
...
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
,
}
...
...
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'
),
...
...
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