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
722bf786
Unverified
Commit
722bf786
authored
Jul 17, 2018
by
老广
Committed by
GitHub
Jul 17, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1542 from jumpserver/dev
Dev to master
parents
91b3b7ce
2cb5876d
Hide whitespace changes
Inline
Side-by-side
Showing
50 changed files
with
991 additions
and
463 deletions
+991
-463
README.md
README.md
+5
-5
__init__.py
apps/__init__.py
+1
-1
asset.py
apps/assets/api/asset.py
+22
-1
asset.py
apps/assets/forms/asset.py
+2
-2
user.py
apps/assets/forms/user.py
+25
-4
asset.py
apps/assets/models/asset.py
+14
-0
base.py
apps/assets/models/base.py
+1
-1
user.py
apps/assets/models/user.py
+10
-0
asset.py
apps/assets/serializers/asset.py
+1
-1
system_user.py
apps/assets/serializers/system_user.py
+12
-2
_system_user.html
apps/assets/templates/assets/_system_user.html
+42
-4
admin_user_list.html
apps/assets/templates/assets/admin_user_list.html
+1
-4
asset_create.html
apps/assets/templates/assets/asset_create.html
+6
-5
asset_update.html
apps/assets/templates/assets/asset_update.html
+1
-0
domain_list.html
apps/assets/templates/assets/domain_list.html
+8
-3
gateway_create_update.html
apps/assets/templates/assets/gateway_create_update.html
+14
-5
system_user_detail.html
apps/assets/templates/assets/system_user_detail.html
+28
-13
system_user_list.html
apps/assets/templates/assets/system_user_list.html
+6
-5
system_user_update.html
apps/assets/templates/assets/system_user_update.html
+0
-1
api_urls.py
apps/assets/urls/api_urls.py
+2
-0
views_urls.py
apps/assets/urls/views_urls.py
+0
-1
utils.py
apps/assets/utils.py
+2
-1
domain.py
apps/assets/views/domain.py
+0
-5
forms.py
apps/common/forms.py
+20
-6
security_setting.html
apps/common/templates/common/security_setting.html
+2
-2
django.mo
apps/i18n/zh/LC_MESSAGES/django.mo
+0
-0
django.po
apps/i18n/zh/LC_MESSAGES/django.po
+339
-245
settings.py
apps/jumpserver/settings.py
+6
-2
inventory.py
apps/ops/inventory.py
+1
-1
api.py
apps/perms/api.py
+4
-4
views_urls.py
apps/perms/urls/views_urls.py
+7
-9
jumpserver.js
apps/static/js/jumpserver.js
+6
-5
_footer.html
apps/templates/_footer.html
+1
-1
api.py
apps/terminal/api.py
+64
-36
session_list.html
apps/terminal/templates/terminal/session_list.html
+2
-0
api.py
apps/users/api.py
+85
-24
authentication.py
apps/users/models/authentication.py
+28
-0
login.html
apps/users/templates/users/login.html
+5
-1
login_log_list.html
apps/users/templates/users/login_log_list.html
+6
-0
user_detail.html
apps/users/templates/users/user_detail.html
+46
-4
user_list.html
apps/users/templates/users/user_list.html
+1
-1
api_urls.py
apps/users/urls/api_urls.py
+2
-0
views_urls.py
apps/users/urls/views_urls.py
+20
-20
utils.py
apps/users/utils.py
+46
-6
login.py
apps/users/views/login.py
+72
-17
user.py
apps/users/views/user.py
+8
-2
config_example.py
config_example.py
+13
-11
deb_requirements.txt
requirements/deb_requirements.txt
+1
-1
requirements.txt
requirements/requirements.txt
+1
-1
make_migrations.sh
utils/make_migrations.sh
+2
-0
No files found.
README.md
View file @
722bf786
...
@@ -19,25 +19,25 @@ Jumpserver采纳分布式架构,支持多机房跨区域部署,中心节点
...
@@ -19,25 +19,25 @@ Jumpserver采纳分布式架构,支持多机房跨区域部署,中心节点
----
----
### 功能
### 功能
!
[
Jumpserver功能
](
https://jumpserver-release.oss-cn-hangzhou.aliyuncs.com/Jumpserver13.jpg
"Jumpserver功能"
)
!
[
Jumpserver功能
](
https://jumpserver-release.oss-cn-hangzhou.aliyuncs.com/Jumpserver13.jpg
"Jumpserver功能"
)
### 开始使用
### 开始使用
快速开始文档
[
Docker安装
](
http://docs.jumpserver.org/zh/
latest/quickstart
.html
)
快速开始文档
[
Docker安装
](
http://docs.jumpserver.org/zh/
docs/dockerinstall
.html
)
一步一步安装文档
[
详细部署
](
http://docs.jumpserver.org/zh/
latest
/step_by_step.html
)
一步一步安装文档
[
详细部署
](
http://docs.jumpserver.org/zh/
docs
/step_by_step.html
)
也可以查看我们完整文档包括了使用和开发
[
文档
](
http://docs.jumpserver.org
)
也可以查看我们完整文档包括了使用和开发
[
文档
](
http://docs.jumpserver.org
)
### Demo 和 截图
### Demo 和 截图
我们提供了DEMO和截图可以让你快速了解Jumpserver
我们提供了DEMO和截图可以让你快速了解Jumpserver
[
DEMO
](
http://demo.jumpserver.org
)
[
DEMO
](
http://demo.jumpserver.org
)
[
截图
](
http://docs.jumpserver.org/zh/docs/snapshot.html
)
[
截图
](
http://docs.jumpserver.org/zh/docs/snapshot.html
)
### SDK
### SDK
我们还编写了一些SDK,供你其它系统快速和Jumpserver APi交互,
我们还编写了一些SDK,供你其它系统快速和Jumpserver APi交互,
...
...
apps/__init__.py
View file @
722bf786
...
@@ -2,4 +2,4 @@
...
@@ -2,4 +2,4 @@
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
#
#
__version__
=
"1.3.
2
"
__version__
=
"1.3.
3
"
apps/assets/api/asset.py
View file @
722bf786
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
#
#
import
random
from
rest_framework
import
generics
from
rest_framework
import
generics
from
rest_framework.response
import
Response
from
rest_framework.response
import
Response
from
rest_framework_bulk
import
BulkModelViewSet
from
rest_framework_bulk
import
BulkModelViewSet
...
@@ -22,7 +24,8 @@ from ..utils import LabelFilter
...
@@ -22,7 +24,8 @@ from ..utils import LabelFilter
logger
=
get_logger
(
__file__
)
logger
=
get_logger
(
__file__
)
__all__
=
[
__all__
=
[
'AssetViewSet'
,
'AssetListUpdateApi'
,
'AssetViewSet'
,
'AssetListUpdateApi'
,
'AssetRefreshHardwareApi'
,
'AssetAdminUserTestApi'
'AssetRefreshHardwareApi'
,
'AssetAdminUserTestApi'
,
'AssetGatewayApi'
]
]
...
@@ -106,3 +109,20 @@ class AssetAdminUserTestApi(generics.RetrieveAPIView):
...
@@ -106,3 +109,20 @@ class AssetAdminUserTestApi(generics.RetrieveAPIView):
asset
=
get_object_or_404
(
Asset
,
pk
=
asset_id
)
asset
=
get_object_or_404
(
Asset
,
pk
=
asset_id
)
task
=
test_asset_connectability_manual
.
delay
(
asset
)
task
=
test_asset_connectability_manual
.
delay
(
asset
)
return
Response
({
"task"
:
task
.
id
})
return
Response
({
"task"
:
task
.
id
})
class
AssetGatewayApi
(
generics
.
RetrieveAPIView
):
queryset
=
Asset
.
objects
.
all
()
permission_classes
=
(
IsSuperUserOrAppUser
,)
def
retrieve
(
self
,
request
,
*
args
,
**
kwargs
):
asset_id
=
kwargs
.
get
(
'pk'
)
asset
=
get_object_or_404
(
Asset
,
pk
=
asset_id
)
if
asset
.
domain
and
\
asset
.
domain
.
gateways
.
filter
(
protocol
=
asset
.
protocol
)
.
exists
():
gateway
=
random
.
choice
(
asset
.
domain
.
gateways
.
filter
(
protocol
=
asset
.
protocol
))
serializer
=
serializers
.
GatewayWithAuthSerializer
(
instance
=
gateway
)
return
Response
(
serializer
.
data
)
else
:
return
Response
({
"msg"
:
"Not have gateway"
},
status
=
404
)
\ No newline at end of file
apps/assets/forms/asset.py
View file @
722bf786
...
@@ -16,7 +16,7 @@ class AssetCreateForm(forms.ModelForm):
...
@@ -16,7 +16,7 @@ class AssetCreateForm(forms.ModelForm):
fields
=
[
fields
=
[
'hostname'
,
'ip'
,
'public_ip'
,
'port'
,
'comment'
,
'hostname'
,
'ip'
,
'public_ip'
,
'port'
,
'comment'
,
'nodes'
,
'is_active'
,
'admin_user'
,
'labels'
,
'platform'
,
'nodes'
,
'is_active'
,
'admin_user'
,
'labels'
,
'platform'
,
'domain'
,
'domain'
,
'protocol'
,
]
]
widgets
=
{
widgets
=
{
...
@@ -56,7 +56,7 @@ class AssetUpdateForm(forms.ModelForm):
...
@@ -56,7 +56,7 @@ class AssetUpdateForm(forms.ModelForm):
fields
=
[
fields
=
[
'hostname'
,
'ip'
,
'port'
,
'nodes'
,
'is_active'
,
'platform'
,
'hostname'
,
'ip'
,
'port'
,
'nodes'
,
'is_active'
,
'platform'
,
'public_ip'
,
'number'
,
'comment'
,
'admin_user'
,
'labels'
,
'public_ip'
,
'number'
,
'comment'
,
'admin_user'
,
'labels'
,
'domain'
,
'domain'
,
'protocol'
,
]
]
widgets
=
{
widgets
=
{
'nodes'
:
forms
.
SelectMultiple
(
attrs
=
{
'nodes'
:
forms
.
SelectMultiple
(
attrs
=
{
...
...
apps/assets/forms/user.py
View file @
722bf786
...
@@ -93,14 +93,21 @@ class SystemUserForm(PasswordAndKeyAuthForm):
...
@@ -93,14 +93,21 @@ class SystemUserForm(PasswordAndKeyAuthForm):
# Because we define custom field, so we need rewrite :method: `save`
# Because we define custom field, so we need rewrite :method: `save`
system_user
=
super
()
.
save
()
system_user
=
super
()
.
save
()
password
=
self
.
cleaned_data
.
get
(
'password'
,
''
)
or
None
password
=
self
.
cleaned_data
.
get
(
'password'
,
''
)
or
None
login_mode
=
self
.
cleaned_data
.
get
(
'login_mode'
,
''
)
or
None
protocol
=
self
.
cleaned_data
.
get
(
'protocol'
)
or
None
auto_generate_key
=
self
.
cleaned_data
.
get
(
'auto_generate_key'
,
False
)
auto_generate_key
=
self
.
cleaned_data
.
get
(
'auto_generate_key'
,
False
)
private_key
,
public_key
=
super
()
.
gen_keys
()
private_key
,
public_key
=
super
()
.
gen_keys
()
if
login_mode
==
SystemUser
.
MANUAL_LOGIN
or
protocol
==
SystemUser
.
TELNET_PROTOCOL
:
system_user
.
auto_push
=
0
system_user
.
save
()
if
auto_generate_key
:
if
auto_generate_key
:
logger
.
info
(
'Auto generate key and set system user auth'
)
logger
.
info
(
'Auto generate key and set system user auth'
)
system_user
.
auto_gen_auth
()
system_user
.
auto_gen_auth
()
else
:
else
:
system_user
.
set_auth
(
password
=
password
,
private_key
=
private_key
,
public_key
=
public_key
)
system_user
.
set_auth
(
password
=
password
,
private_key
=
private_key
,
public_key
=
public_key
)
return
system_user
return
system_user
def
clean
(
self
):
def
clean
(
self
):
...
@@ -109,12 +116,24 @@ class SystemUserForm(PasswordAndKeyAuthForm):
...
@@ -109,12 +116,24 @@ class SystemUserForm(PasswordAndKeyAuthForm):
if
not
self
.
instance
and
not
auto_generate
:
if
not
self
.
instance
and
not
auto_generate
:
super
()
.
validate_password_key
()
super
()
.
validate_password_key
()
def
is_valid
(
self
):
validated
=
super
()
.
is_valid
()
username
=
self
.
cleaned_data
.
get
(
'username'
)
login_mode
=
self
.
cleaned_data
.
get
(
'login_mode'
)
if
login_mode
==
SystemUser
.
AUTO_LOGIN
and
not
username
:
self
.
add_error
(
"username"
,
_
(
'* Automatic login mode,'
' must fill in the username.'
)
)
return
False
return
validated
class
Meta
:
class
Meta
:
model
=
SystemUser
model
=
SystemUser
fields
=
[
fields
=
[
'name'
,
'username'
,
'protocol'
,
'auto_generate_key'
,
'name'
,
'username'
,
'protocol'
,
'auto_generate_key'
,
'password'
,
'private_key_file'
,
'auto_push'
,
'sudo'
,
'password'
,
'private_key_file'
,
'auto_push'
,
'sudo'
,
'comment'
,
'shell'
,
'priority'
,
'comment'
,
'shell'
,
'priority'
,
'login_mode'
,
]
]
widgets
=
{
widgets
=
{
'name'
:
forms
.
TextInput
(
attrs
=
{
'placeholder'
:
_
(
'Name'
)}),
'name'
:
forms
.
TextInput
(
attrs
=
{
'placeholder'
:
_
(
'Name'
)}),
...
@@ -124,5 +143,8 @@ class SystemUserForm(PasswordAndKeyAuthForm):
...
@@ -124,5 +143,8 @@ class SystemUserForm(PasswordAndKeyAuthForm):
'name'
:
'* required'
,
'name'
:
'* required'
,
'username'
:
'* required'
,
'username'
:
'* required'
,
'auto_push'
:
_
(
'Auto push system user to asset'
),
'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'
),
'priority'
:
_
(
'High level will be using login asset as default, '
}
'if user was granted more than 2 system user'
),
\ No newline at end of file
'login_mode'
:
_
(
'If you choose manual login mode, you do not '
'need to fill in the username and password.'
)
}
apps/assets/models/asset.py
View file @
722bf786
...
@@ -57,13 +57,27 @@ class Asset(models.Model):
...
@@ -57,13 +57,27 @@ class Asset(models.Model):
(
'MacOS'
,
'MacOS'
),
(
'MacOS'
,
'MacOS'
),
(
'BSD'
,
'BSD'
),
(
'BSD'
,
'BSD'
),
(
'Windows'
,
'Windows'
),
(
'Windows'
,
'Windows'
),
(
'Windows2016'
,
'Windows(2016)'
),
(
'Other'
,
'Other'
),
(
'Other'
,
'Other'
),
)
)
SSH_PROTOCOL
=
'ssh'
RDP_PROTOCOL
=
'rdp'
TELNET_PROTOCOL
=
'telnet'
PROTOCOL_CHOICES
=
(
(
SSH_PROTOCOL
,
'ssh'
),
(
RDP_PROTOCOL
,
'rdp'
),
(
TELNET_PROTOCOL
,
'telnet (beta)'
),
)
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
ip
=
models
.
GenericIPAddressField
(
max_length
=
32
,
verbose_name
=
_
(
'IP'
),
ip
=
models
.
GenericIPAddressField
(
max_length
=
32
,
verbose_name
=
_
(
'IP'
),
db_index
=
True
)
db_index
=
True
)
hostname
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
hostname
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
'Hostname'
))
verbose_name
=
_
(
'Hostname'
))
protocol
=
models
.
CharField
(
max_length
=
128
,
default
=
SSH_PROTOCOL
,
choices
=
PROTOCOL_CHOICES
,
verbose_name
=
_
(
'Protocol'
))
port
=
models
.
IntegerField
(
default
=
22
,
verbose_name
=
_
(
'Port'
))
port
=
models
.
IntegerField
(
default
=
22
,
verbose_name
=
_
(
'Port'
))
platform
=
models
.
CharField
(
max_length
=
128
,
choices
=
PLATFORM_CHOICES
,
platform
=
models
.
CharField
(
max_length
=
128
,
choices
=
PLATFORM_CHOICES
,
default
=
'Linux'
,
verbose_name
=
_
(
'Platform'
))
default
=
'Linux'
,
verbose_name
=
_
(
'Platform'
))
...
...
apps/assets/models/base.py
View file @
722bf786
...
@@ -19,7 +19,7 @@ signer = get_signer()
...
@@ -19,7 +19,7 @@ signer = get_signer()
class
AssetUser
(
models
.
Model
):
class
AssetUser
(
models
.
Model
):
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
name
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
'Name'
))
name
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
'Name'
))
username
=
models
.
CharField
(
max_length
=
32
,
verbose_name
=
_
(
'Username'
),
validators
=
[
alphanumeric
])
username
=
models
.
CharField
(
max_length
=
32
,
blank
=
True
,
verbose_name
=
_
(
'Username'
),
validators
=
[
alphanumeric
])
_password
=
models
.
CharField
(
max_length
=
256
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Password'
))
_password
=
models
.
CharField
(
max_length
=
256
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Password'
))
_private_key
=
models
.
TextField
(
max_length
=
4096
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'SSH private key'
),
validators
=
[
private_key_validator
,
])
_private_key
=
models
.
TextField
(
max_length
=
4096
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'SSH private key'
),
validators
=
[
private_key_validator
,
])
_public_key
=
models
.
TextField
(
max_length
=
4096
,
blank
=
True
,
verbose_name
=
_
(
'SSH public key'
))
_public_key
=
models
.
TextField
(
max_length
=
4096
,
blank
=
True
,
verbose_name
=
_
(
'SSH public key'
))
...
...
apps/assets/models/user.py
View file @
722bf786
...
@@ -95,9 +95,18 @@ class AdminUser(AssetUser):
...
@@ -95,9 +95,18 @@ class AdminUser(AssetUser):
class
SystemUser
(
AssetUser
):
class
SystemUser
(
AssetUser
):
SSH_PROTOCOL
=
'ssh'
SSH_PROTOCOL
=
'ssh'
RDP_PROTOCOL
=
'rdp'
RDP_PROTOCOL
=
'rdp'
TELNET_PROTOCOL
=
'telnet'
PROTOCOL_CHOICES
=
(
PROTOCOL_CHOICES
=
(
(
SSH_PROTOCOL
,
'ssh'
),
(
SSH_PROTOCOL
,
'ssh'
),
(
RDP_PROTOCOL
,
'rdp'
),
(
RDP_PROTOCOL
,
'rdp'
),
(
TELNET_PROTOCOL
,
'telnet (beta)'
),
)
AUTO_LOGIN
=
'auto'
MANUAL_LOGIN
=
'manual'
LOGIN_MODE_CHOICES
=
(
(
AUTO_LOGIN
,
_
(
'Automatic login'
)),
(
MANUAL_LOGIN
,
_
(
'Manually login'
))
)
)
nodes
=
models
.
ManyToManyField
(
'assets.Node'
,
blank
=
True
,
verbose_name
=
_
(
"Nodes"
))
nodes
=
models
.
ManyToManyField
(
'assets.Node'
,
blank
=
True
,
verbose_name
=
_
(
"Nodes"
))
...
@@ -107,6 +116,7 @@ class SystemUser(AssetUser):
...
@@ -107,6 +116,7 @@ class SystemUser(AssetUser):
auto_push
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
'Auto push'
))
auto_push
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
'Auto push'
))
sudo
=
models
.
TextField
(
default
=
'/bin/whoami'
,
verbose_name
=
_
(
'Sudo'
))
sudo
=
models
.
TextField
(
default
=
'/bin/whoami'
,
verbose_name
=
_
(
'Sudo'
))
shell
=
models
.
CharField
(
max_length
=
64
,
default
=
'/bin/bash'
,
verbose_name
=
_
(
'Shell'
))
shell
=
models
.
CharField
(
max_length
=
64
,
default
=
'/bin/bash'
,
verbose_name
=
_
(
'Shell'
))
login_mode
=
models
.
CharField
(
choices
=
LOGIN_MODE_CHOICES
,
default
=
AUTO_LOGIN
,
max_length
=
10
,
verbose_name
=
_
(
'Login mode'
))
def
__str__
(
self
):
def
__str__
(
self
):
return
'{0.name}({0.username})'
.
format
(
self
)
return
'{0.name}({0.username})'
.
format
(
self
)
...
...
apps/assets/serializers/asset.py
View file @
722bf786
...
@@ -43,7 +43,7 @@ class AssetGrantedSerializer(serializers.ModelSerializer):
...
@@ -43,7 +43,7 @@ class AssetGrantedSerializer(serializers.ModelSerializer):
fields
=
(
fields
=
(
"id"
,
"hostname"
,
"ip"
,
"port"
,
"system_users_granted"
,
"id"
,
"hostname"
,
"ip"
,
"port"
,
"system_users_granted"
,
"is_active"
,
"system_users_join"
,
"os"
,
'domain'
,
"is_active"
,
"system_users_join"
,
"os"
,
'domain'
,
"platform"
,
"comment"
"platform"
,
"comment"
,
"protocol"
,
)
)
@staticmethod
@staticmethod
...
...
apps/assets/serializers/system_user.py
View file @
722bf786
...
@@ -18,6 +18,13 @@ class SystemUserSerializer(serializers.ModelSerializer):
...
@@ -18,6 +18,13 @@ class SystemUserSerializer(serializers.ModelSerializer):
model
=
SystemUser
model
=
SystemUser
exclude
=
(
'_password'
,
'_private_key'
,
'_public_key'
)
exclude
=
(
'_password'
,
'_private_key'
,
'_public_key'
)
def
get_field_names
(
self
,
declared_fields
,
info
):
fields
=
super
(
SystemUserSerializer
,
self
)
.
get_field_names
(
declared_fields
,
info
)
fields
.
extend
([
'get_login_mode_display'
,
])
return
fields
@staticmethod
@staticmethod
def
get_unreachable_assets
(
obj
):
def
get_unreachable_assets
(
obj
):
return
obj
.
unreachable_assets
return
obj
.
unreachable_assets
...
@@ -46,7 +53,7 @@ class SystemUserAuthSerializer(AuthSerializer):
...
@@ -46,7 +53,7 @@ class SystemUserAuthSerializer(AuthSerializer):
model
=
SystemUser
model
=
SystemUser
fields
=
[
fields
=
[
"id"
,
"name"
,
"username"
,
"protocol"
,
"id"
,
"name"
,
"username"
,
"protocol"
,
"password"
,
"private_key"
,
"
login_mode"
,
"
password"
,
"private_key"
,
]
]
...
@@ -56,7 +63,10 @@ class AssetSystemUserSerializer(serializers.ModelSerializer):
...
@@ -56,7 +63,10 @@ class AssetSystemUserSerializer(serializers.ModelSerializer):
"""
"""
class
Meta
:
class
Meta
:
model
=
SystemUser
model
=
SystemUser
fields
=
(
'id'
,
'name'
,
'username'
,
'priority'
,
'protocol'
,
'comment'
,)
fields
=
(
'id'
,
'name'
,
'username'
,
'priority'
,
'protocol'
,
'comment'
,
'login_mode'
)
class
SystemUserSimpleSerializer
(
serializers
.
ModelSerializer
):
class
SystemUserSimpleSerializer
(
serializers
.
ModelSerializer
):
...
...
apps/assets/templates/assets/_system_user.html
View file @
722bf786
...
@@ -36,12 +36,13 @@
...
@@ -36,12 +36,13 @@
{% endif %}
{% endif %}
<h3>
{% trans 'Basic' %}
</h3>
<h3>
{% trans 'Basic' %}
</h3>
{% bootstrap_field form.name layout="horizontal" %}
{% bootstrap_field form.name layout="horizontal" %}
{% bootstrap_field form.login_mode layout="horizontal" %}
{% bootstrap_field form.username layout="horizontal" %}
{% bootstrap_field form.username layout="horizontal" %}
{% bootstrap_field form.priority layout="horizontal" %}
{% bootstrap_field form.priority layout="horizontal" %}
{% bootstrap_field form.protocol layout="horizontal" %}
{% bootstrap_field form.protocol layout="horizontal" %}
<h3
id=
"auth_title_id"
>
{% trans 'Auth' %}
</h3>
{% block auth %}
{% block auth %}
<h3>
{% trans 'Auth' %}
</h3>
<div
class=
"auto-generate"
>
<div
class=
"auto-generate"
>
<div
class=
"form-group"
>
<div
class=
"form-group"
>
<label
for=
"{{ form.auto_generate_key.id_for_label }}"
class=
"col-sm-2 control-label"
>
{% trans 'Auto generate key' %}
</label>
<label
for=
"{{ form.auto_generate_key.id_for_label }}"
class=
"col-sm-2 control-label"
>
{% trans 'Auto generate key' %}
</label>
...
@@ -80,15 +81,22 @@
...
@@ -80,15 +81,22 @@
{% endblock %}
{% endblock %}
{% block custom_foot_js %}
{% block custom_foot_js %}
<script>
<script>
var
auto_generate_key
=
'#'
+
'{{ form.auto_generate_key.id_for_label }}'
;
var
protocol_id
=
'#'
+
'{{ form.protocol.id_for_label }}'
;
var
protocol_id
=
'#'
+
'{{ form.protocol.id_for_label }}'
;
var
login_mode_id
=
'#'
+
'{{ form.login_mode.id_for_label }}'
;
var
auto_generate_key
=
'#'
+
'{{ form.auto_generate_key.id_for_label }}'
;
var
password_id
=
'#'
+
'{{ form.password.id_for_label }}'
;
var
private_key_id
=
'#'
+
'{{ form.private_key_file.id_for_label }}'
;
var
private_key_id
=
'#'
+
'{{ form.private_key_file.id_for_label }}'
;
var
auto_push_id
=
'#'
+
'{{ form.auto_push.id_for_label }}'
;
var
auto_push_id
=
'#'
+
'{{ form.auto_push.id_for_label }}'
;
var
sudo_id
=
'#'
+
'{{ form.sudo.id_for_label }}'
;
var
sudo_id
=
'#'
+
'{{ form.sudo.id_for_label }}'
;
var
shell_id
=
'#'
+
'{{ form.shell.id_for_label }}'
;
var
shell_id
=
'#'
+
'{{ form.shell.id_for_label }}'
;
var
need_change_field
=
[
var
need_change_field
=
[
auto_generate_key
,
private_key_id
,
auto_push_id
,
sudo_id
,
shell_id
auto_generate_key
,
private_key_id
,
auto_push_id
,
sudo_id
,
shell_id
];
];
var
need_change_field_login_mode
=
[
auto_generate_key
,
private_key_id
,
auto_push_id
,
password_id
];
function
protocolChange
()
{
function
protocolChange
()
{
if
(
$
(
protocol_id
+
" option:selected"
).
text
()
===
'rdp'
)
{
if
(
$
(
protocol_id
+
" option:selected"
).
text
()
===
'rdp'
)
{
...
@@ -96,7 +104,19 @@ function protocolChange() {
...
@@ -96,7 +104,19 @@ function protocolChange() {
$
.
each
(
need_change_field
,
function
(
index
,
value
)
{
$
.
each
(
need_change_field
,
function
(
index
,
value
)
{
$
(
value
).
closest
(
'.form-group'
).
addClass
(
'hidden'
)
$
(
value
).
closest
(
'.form-group'
).
addClass
(
'hidden'
)
});
});
}
else
{
}
else
if
(
$
(
protocol_id
+
" option:selected"
).
text
()
===
'telnet (beta)'
)
{
$
(
'.auth-fields'
).
removeClass
(
'hidden'
);
$
.
each
(
need_change_field
,
function
(
index
,
value
)
{
$
(
value
).
closest
(
'.form-group'
).
addClass
(
'hidden'
)
});
}
else
{
if
(
$
(
login_mode_id
).
val
()
===
'manual'
){
$
(
sudo_id
).
closest
(
'.form-group'
).
removeClass
(
'hidden'
);
$
(
shell_id
).
closest
(
'.form-group'
).
removeClass
(
'hidden'
);
return
}
authFieldsDisplay
();
authFieldsDisplay
();
$
.
each
(
need_change_field
,
function
(
index
,
value
)
{
$
.
each
(
need_change_field
,
function
(
index
,
value
)
{
$
(
value
).
closest
(
'.form-group'
).
removeClass
(
'hidden'
)
$
(
value
).
closest
(
'.form-group'
).
removeClass
(
'hidden'
)
...
@@ -111,18 +131,35 @@ function authFieldsDisplay() {
...
@@ -111,18 +131,35 @@ function authFieldsDisplay() {
$
(
'.auth-fields'
).
removeClass
(
'hidden'
);
$
(
'.auth-fields'
).
removeClass
(
'hidden'
);
}
}
}
}
function
loginModeChange
(){
if
(
$
(
login_mode_id
).
val
()
===
'manual'
){
$
(
'#auth_title_id'
).
addClass
(
'hidden'
);
$
.
each
(
need_change_field_login_mode
,
function
(
index
,
value
){
$
(
value
).
closest
(
'.form-group'
).
addClass
(
'hidden'
)
})
}
else
if
(
$
(
login_mode_id
).
val
()
===
'auto'
){
$
(
'#auth_title_id'
).
removeClass
(
'hidden'
);
$
(
password_id
).
closest
(
'.form-group'
).
removeClass
(
'hidden'
)
protocolChange
();
}
}
$
(
document
).
ready
(
function
()
{
$
(
document
).
ready
(
function
()
{
$
(
'.select2'
).
select2
();
$
(
'.select2'
).
select2
();
authFieldsDisplay
();
authFieldsDisplay
();
protocolChange
();
protocolChange
();
loginModeChange
();
})
})
.
on
(
'change'
,
protocol_id
,
function
(){
.
on
(
'change'
,
protocol_id
,
function
(){
protocolChange
();
protocolChange
();
})
})
.
on
(
'change'
,
auto_generate_key
,
function
(){
.
on
(
'change'
,
auto_generate_key
,
function
(){
authFieldsDisplay
();
authFieldsDisplay
();
});
})
.
on
(
'change'
,
login_mode_id
,
function
(){
loginModeChange
();
})
</script>
</script>
{% endblock %}
{% endblock %}
\ No newline at end of file
apps/assets/templates/assets/admin_user_list.html
View file @
722bf786
...
@@ -5,7 +5,7 @@
...
@@ -5,7 +5,7 @@
{% block help_message %}
{% block help_message %}
<div
class=
"alert alert-info help-message"
>
<div
class=
"alert alert-info help-message"
>
管理用户是
服务器
的root,或拥有 NOPASSWD: ALL sudo权限的用户,Jumpserver使用该用户来 `推送系统用户`、`获取资产硬件信息`等。
管理用户是
资产(被控服务器)上
的root,或拥有 NOPASSWD: ALL sudo权限的用户,Jumpserver使用该用户来 `推送系统用户`、`获取资产硬件信息`等。
Windows或其它硬件可以随意设置一个
Windows或其它硬件可以随意设置一个
</div>
</div>
{% endblock %}
{% endblock %}
...
@@ -107,6 +107,3 @@ $(document).ready(function(){
...
@@ -107,6 +107,3 @@ $(document).ready(function(){
});
});
</script>
</script>
{% endblock %}
{% endblock %}
apps/assets/templates/assets/asset_create.html
View file @
722bf786
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
{% bootstrap_field form.hostname layout="horizontal" %}
{% bootstrap_field form.hostname layout="horizontal" %}
{% bootstrap_field form.platform layout="horizontal" %}
{% bootstrap_field form.platform layout="horizontal" %}
{% bootstrap_field form.ip layout="horizontal" %}
{% bootstrap_field form.ip layout="horizontal" %}
{% bootstrap_field form.protocol layout="horizontal" %}
{% bootstrap_field form.port layout="horizontal" %}
{% bootstrap_field form.port layout="horizontal" %}
{% bootstrap_field form.public_ip layout="horizontal" %}
{% bootstrap_field form.public_ip layout="horizontal" %}
{% bootstrap_field form.domain layout="horizontal" %}
{% bootstrap_field form.domain layout="horizontal" %}
...
@@ -85,14 +86,14 @@ $(document).ready(function () {
...
@@ -85,14 +86,14 @@ $(document).ready(function () {
allowClear
:
true
,
allowClear
:
true
,
templateSelection
:
format
templateSelection
:
format
});
});
$
(
"#id_p
latform
"
).
change
(
function
(){
$
(
"#id_p
rotocol
"
).
change
(
function
(){
var
p
latform
=
$
(
"#id_platform
option:selected"
).
text
();
var
p
rotocol
=
$
(
"#id_protocol
option:selected"
).
text
();
var
port
=
22
;
var
port
=
22
;
if
(
p
latform
===
'Windows
'
){
if
(
p
rotocol
===
'rdp
'
){
port
=
3389
;
port
=
3389
;
}
}
if
(
p
latform
===
'Other
'
){
if
(
p
rotocol
===
'telnet (beta)
'
){
port
=
null
;
port
=
23
;
}
}
$
(
"#id_port"
).
val
(
port
);
$
(
"#id_port"
).
val
(
port
);
});
});
...
...
apps/assets/templates/assets/asset_update.html
View file @
722bf786
...
@@ -21,6 +21,7 @@
...
@@ -21,6 +21,7 @@
<h3>
{% trans 'Basic' %}
</h3>
<h3>
{% trans 'Basic' %}
</h3>
{% bootstrap_field form.hostname layout="horizontal" %}
{% bootstrap_field form.hostname layout="horizontal" %}
{% bootstrap_field form.ip layout="horizontal" %}
{% bootstrap_field form.ip layout="horizontal" %}
{% bootstrap_field form.protocol layout="horizontal" %}
{% bootstrap_field form.port layout="horizontal" %}
{% bootstrap_field form.port layout="horizontal" %}
{% bootstrap_field form.platform layout="horizontal" %}
{% bootstrap_field form.platform layout="horizontal" %}
{% bootstrap_field form.public_ip layout="horizontal" %}
{% bootstrap_field form.public_ip layout="horizontal" %}
...
...
apps/assets/templates/assets/domain_list.html
View file @
722bf786
{% extends '_base_list.html' %}
{% extends '_base_list.html' %}
{% load i18n static %}
{% load i18n static %}
{% block table_search %}{% endblock %}
{% block table_search %}{% endblock %}
{% block help_message %}
<div
class=
"alert alert-info help-message"
>
网域功能是为了解决部分环境(如:混合云)无法直接连接而新增的功能,原理是通过网关服务器进行跳转登
录。
</div>
{% endblock %}
{% block table_container %}
{% block table_container %}
<div
class=
"uc pull-left m-r-5"
>
<div
class=
"uc pull-left m-r-5"
>
<a
href=
"{% url 'assets:domain-create' %}"
class=
"btn btn-sm btn-primary"
>
{% trans "Create domain" %}
</a>
<a
href=
"{% url 'assets:domain-create' %}"
class=
"btn btn-sm btn-primary"
>
{% trans "Create domain" %}
</a>
...
@@ -69,6 +77,3 @@ $(document).ready(function(){
...
@@ -69,6 +77,3 @@ $(document).ready(function(){
});
});
</script>
</script>
{% endblock %}
{% endblock %}
apps/assets/templates/assets/gateway_create_update.html
View file @
722bf786
...
@@ -42,7 +42,7 @@
...
@@ -42,7 +42,7 @@
{% bootstrap_field form.domain layout="horizontal" %}
{% bootstrap_field form.domain layout="horizontal" %}
{% block auth %}
{% block auth %}
<h3>
{% trans 'Auth' %}
</h3>
<h3
id=
"auth_title"
>
{% trans 'Auth' %}
</h3>
<div
class=
"auth-fields"
>
<div
class=
"auth-fields"
>
{% bootstrap_field form.username layout="horizontal" %}
{% bootstrap_field form.username layout="horizontal" %}
{% bootstrap_field form.password layout="horizontal" %}
{% bootstrap_field form.password layout="horizontal" %}
...
@@ -72,14 +72,23 @@
...
@@ -72,14 +72,23 @@
var
protocol_id
=
'#'
+
'{{ form.protocol.id_for_label }}'
;
var
protocol_id
=
'#'
+
'{{ form.protocol.id_for_label }}'
;
var
private_key_id
=
'#'
+
'{{ form.private_key_file.id_for_label }}'
;
var
private_key_id
=
'#'
+
'{{ form.private_key_file.id_for_label }}'
;
var
port
=
'#'
+
'{{ form.port.id_for_label }}'
;
var
port
=
'#'
+
'{{ form.port.id_for_label }}'
;
var
username
=
'#'
+
'{{ form.username.id_for_label }}'
;
var
password
=
'#'
+
'{{ form.password.id_for_label }}'
;
var
auth_title
=
'#auth_title'
;
function
protocolChange
()
{
function
protocolChange
()
{
if
(
$
(
protocol_id
+
" option:selected"
).
text
()
===
'rdp'
)
{
if
(
$
(
protocol_id
+
" option:selected"
).
text
()
===
'rdp'
)
{
$
(
port
).
val
(
3389
);
{
#
$
(
port
).
val
(
3389
);
#
}
$
(
private_key_id
).
closest
(
'.form-group'
).
addClass
(
'hidden'
)
$
(
private_key_id
).
closest
(
'.form-group'
).
addClass
(
'hidden'
);
$
(
username
).
closest
(
'.form-group'
).
addClass
(
'hidden'
);
$
(
password
).
closest
(
'.form-group'
).
addClass
(
'hidden'
);
$
(
auth_title
).
addClass
(
'hidden'
);
}
else
{
}
else
{
$
(
port
).
val
(
22
);
{
#
$
(
port
).
val
(
22
);
#
}
$
(
private_key_id
).
closest
(
'.form-group'
).
removeClass
(
'hidden'
)
$
(
private_key_id
).
closest
(
'.form-group'
).
removeClass
(
'hidden'
);
$
(
username
).
closest
(
'.form-group'
).
removeClass
(
'hidden'
);
$
(
password
).
closest
(
'.form-group'
).
removeClass
(
'hidden'
);
$
(
auth_title
).
removeClass
(
'hidden'
);
}
}
}
}
...
...
apps/assets/templates/assets/system_user_detail.html
View file @
722bf786
...
@@ -62,6 +62,10 @@
...
@@ -62,6 +62,10 @@
<td>
{% trans 'Username' %}:
</td>
<td>
{% trans 'Username' %}:
</td>
<td><b>
{{ system_user.username }}
</b></td>
<td><b>
{{ system_user.username }}
</b></td>
</tr>
</tr>
<tr>
<td>
{% trans 'Login mode' %}:
</td>
<td><b>
{{ system_user.get_login_mode_display }}
</b></td>
</tr>
<tr>
<tr>
<td>
{% trans 'Protocol' %}:
</td>
<td>
{% trans 'Protocol' %}:
</td>
<td><b
id=
"id_protocol_type"
>
{{ system_user.protocol }}
</b></td>
<td><b
id=
"id_protocol_type"
>
{{ system_user.protocol }}
</b></td>
...
@@ -148,15 +152,14 @@
...
@@ -148,15 +152,14 @@
</span>
</span>
</td>
</td>
</tr>
</tr>
{#
<tr>
#}
<tr>
{#
<td
width=
"50%"
>
{% trans 'Clear auth' %}:
</td>
#}
<td
width=
"50%"
>
{% trans 'Clear auth' %}:
</td>
{#
<td>
#}
<td>
{#
<span
style=
"float: right"
>
#}
<span
style=
"float: right"
>
{#
<button
type=
"button"
class=
"btn btn-primary btn-xs btn-clear-auth"
style=
"width: 54px"
>
{% trans 'Clear' %}
</button>
#}
<button
type=
"button"
class=
"btn btn-primary btn-xs btn-clear-auth"
style=
"width: 54px"
>
{% trans 'Clear' %}
</button>
{#
</span>
#}
</span>
{#
</td>
#}
</td>
{#
</tr>
#}
</tr>
{#
<tr>
#}
{#
<tr>
#}
{#
<td
width=
"50%"
>
{% trans 'Change auth period' %}:
</td>
#}
{#
<td
width=
"50%"
>
{% trans 'Change auth period' %}:
</td>
#}
...
@@ -333,10 +336,22 @@ $(document).ready(function () {
...
@@ -333,10 +336,22 @@ $(document).ready(function () {
});
});
}).
on
(
'click'
,
'.btn-clear-auth'
,
function
()
{
}).
on
(
'click'
,
'.btn-clear-auth'
,
function
()
{
var
the_url
=
'{% url "api-assets:system-user-auth-info" pk=system_user.id %}'
;
var
the_url
=
'{% url "api-assets:system-user-auth-info" pk=system_user.id %}'
;
APIUpdateAttr
({
var
name
=
'{{ system_user.name }}'
;
url
:
the_url
,
swal
({
method
:
'DELETE'
,
title
:
'你确定清除该系统用户的认证信息吗 ?'
,
success_message
:
"{% trans 'Clear auth' %}"
+
" {% trans 'success' %}"
text
:
" ["
+
name
+
"] "
,
type
:
"warning"
,
showCancelButton
:
true
,
cancelButtonText
:
'取消'
,
confirmButtonColor
:
"#ed5565"
,
confirmButtonText
:
'确认'
,
closeOnConfirm
:
true
},
function
()
{
APIUpdateAttr
({
url
:
the_url
,
method
:
'DELETE'
,
success_message
:
"{% trans 'Clear auth' %}"
+
" {% trans 'success' %}"
});
});
});
})
})
</script>
</script>
...
...
apps/assets/templates/assets/system_user_list.html
View file @
722bf786
...
@@ -26,6 +26,7 @@
...
@@ -26,6 +26,7 @@
<th
class=
"text-center"
>
{% trans 'Name' %}
</th>
<th
class=
"text-center"
>
{% trans 'Name' %}
</th>
<th
class=
"text-center"
>
{% trans 'Username' %}
</th>
<th
class=
"text-center"
>
{% trans 'Username' %}
</th>
<th
class=
"text-center"
>
{% trans 'Protocol' %}
</th>
<th
class=
"text-center"
>
{% trans 'Protocol' %}
</th>
<th
class=
"text-center"
>
{% trans 'Login mode' %}
</th>
<th
class=
"text-center"
>
{% trans 'Asset' %}
</th>
<th
class=
"text-center"
>
{% trans 'Asset' %}
</th>
<th
class=
"text-center"
>
{% trans 'Reachable' %}
</th>
<th
class=
"text-center"
>
{% trans 'Reachable' %}
</th>
<th
class=
"text-center"
>
{% trans 'Unreachable' %}
</th>
<th
class=
"text-center"
>
{% trans 'Unreachable' %}
</th>
...
@@ -48,7 +49,7 @@ function initTable() {
...
@@ -48,7 +49,7 @@ function initTable() {
var
detail_btn
=
'<a href="{% url "assets:system-user-detail" pk=DEFAULT_PK %}">'
+
cellData
+
'</a>'
;
var
detail_btn
=
'<a href="{% url "assets:system-user-detail" pk=DEFAULT_PK %}">'
+
cellData
+
'</a>'
;
$
(
td
).
html
(
detail_btn
.
replace
(
'{{ DEFAULT_PK }}'
,
rowData
.
id
));
$
(
td
).
html
(
detail_btn
.
replace
(
'{{ DEFAULT_PK }}'
,
rowData
.
id
));
}},
}},
{
targets
:
5
,
createdCell
:
function
(
td
,
cellData
)
{
{
targets
:
6
,
createdCell
:
function
(
td
,
cellData
)
{
var
innerHtml
=
""
;
var
innerHtml
=
""
;
if
(
cellData
!==
0
)
{
if
(
cellData
!==
0
)
{
innerHtml
=
"<span class='text-navy'>"
+
cellData
+
"</span>"
;
innerHtml
=
"<span class='text-navy'>"
+
cellData
+
"</span>"
;
...
@@ -57,7 +58,7 @@ function initTable() {
...
@@ -57,7 +58,7 @@ function initTable() {
}
}
$
(
td
).
html
(
'<span href="javascript:void(0);" data-toggle="tooltip" title="'
+
cellData
+
'">'
+
innerHtml
+
'</span>'
);
$
(
td
).
html
(
'<span href="javascript:void(0);" data-toggle="tooltip" title="'
+
cellData
+
'">'
+
innerHtml
+
'</span>'
);
}},
}},
{
targets
:
6
,
createdCell
:
function
(
td
,
cellData
)
{
{
targets
:
7
,
createdCell
:
function
(
td
,
cellData
)
{
var
innerHtml
=
""
;
var
innerHtml
=
""
;
if
(
cellData
!==
0
)
{
if
(
cellData
!==
0
)
{
innerHtml
=
"<span class='text-danger'>"
+
cellData
+
"</span>"
;
innerHtml
=
"<span class='text-danger'>"
+
cellData
+
"</span>"
;
...
@@ -66,7 +67,7 @@ function initTable() {
...
@@ -66,7 +67,7 @@ function initTable() {
}
}
$
(
td
).
html
(
'<span href="javascript:void(0);" data-toggle="tooltip" title="'
+
cellData
+
'">'
+
innerHtml
+
'</span>'
);
$
(
td
).
html
(
'<span href="javascript:void(0);" data-toggle="tooltip" title="'
+
cellData
+
'">'
+
innerHtml
+
'</span>'
);
}},
}},
{
targets
:
7
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
{
targets
:
8
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
val
=
0
;
var
val
=
0
;
var
innerHtml
=
""
;
var
innerHtml
=
""
;
var
total
=
rowData
.
assets_amount
;
var
total
=
rowData
.
assets_amount
;
...
@@ -84,14 +85,14 @@ function initTable() {
...
@@ -84,14 +85,14 @@ function initTable() {
$
(
td
).
html
(
'<span href="javascript:void(0);" data-toggle="tooltip" title="'
+
cellData
+
'">'
+
innerHtml
+
'</span>'
);
$
(
td
).
html
(
'<span href="javascript:void(0);" data-toggle="tooltip" title="'
+
cellData
+
'">'
+
innerHtml
+
'</span>'
);
}},
}},
{
targets
:
9
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
{
targets
:
10
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
update_btn
=
'<a href="{% url "assets:system-user-update" pk=DEFAULT_PK %}" class="btn btn-xs m-l-xs btn-info">{% trans "Update" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
);
var
update_btn
=
'<a href="{% url "assets:system-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
);
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
(
update_btn
+
del_btn
)
$
(
td
).
html
(
update_btn
+
del_btn
)
}}],
}}],
ajax_url
:
'{% url "api-assets:system-user-list" %}'
,
ajax_url
:
'{% url "api-assets:system-user-list" %}'
,
columns
:
[
columns
:
[
{
data
:
"id"
},
{
data
:
"name"
},
{
data
:
"username"
},
{
data
:
"protocol"
},
{
data
:
"assets_amount"
},
{
data
:
"id"
},
{
data
:
"name"
},
{
data
:
"username"
},
{
data
:
"protocol"
},
{
data
:
"
get_login_mode_display"
},
{
data
:
"
assets_amount"
},
{
data
:
"reachable_amount"
},
{
data
:
"unreachable_amount"
},
{
data
:
"id"
},
{
data
:
"comment"
},
{
data
:
"id"
}
{
data
:
"reachable_amount"
},
{
data
:
"unreachable_amount"
},
{
data
:
"id"
},
{
data
:
"comment"
},
{
data
:
"id"
}
],
],
op_html
:
$
(
'#actions'
).
html
()
op_html
:
$
(
'#actions'
).
html
()
...
...
apps/assets/templates/assets/system_user_update.html
View file @
722bf786
...
@@ -4,7 +4,6 @@
...
@@ -4,7 +4,6 @@
{% load bootstrap3 %}
{% load bootstrap3 %}
{% block auth %}
{% block auth %}
<h3>
{% trans 'Auth' %}
</h3>
{% bootstrap_field form.password layout="horizontal" %}
{% bootstrap_field form.password layout="horizontal" %}
{% bootstrap_field form.private_key_file layout="horizontal" %}
{% bootstrap_field form.private_key_file layout="horizontal" %}
<div
class=
"form-group"
>
<div
class=
"form-group"
>
...
...
apps/assets/urls/api_urls.py
View file @
722bf786
...
@@ -23,6 +23,8 @@ urlpatterns = [
...
@@ -23,6 +23,8 @@ urlpatterns = [
api
.
AssetRefreshHardwareApi
.
as_view
(),
name
=
'asset-refresh'
),
api
.
AssetRefreshHardwareApi
.
as_view
(),
name
=
'asset-refresh'
),
url
(
r'^v1/assets/(?P<pk>[0-9a-zA-Z\-]{36})/alive/$'
,
url
(
r'^v1/assets/(?P<pk>[0-9a-zA-Z\-]{36})/alive/$'
,
api
.
AssetAdminUserTestApi
.
as_view
(),
name
=
'asset-alive-test'
),
api
.
AssetAdminUserTestApi
.
as_view
(),
name
=
'asset-alive-test'
),
url
(
r'^v1/assets/(?P<pk>[0-9a-zA-Z\-]{36})/gateway/$'
,
api
.
AssetGatewayApi
.
as_view
(),
name
=
'asset-gateway'
),
url
(
r'^v1/admin-user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/$'
,
url
(
r'^v1/admin-user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/$'
,
api
.
ReplaceNodesAdminUserApi
.
as_view
(),
name
=
'replace-nodes-admin-user'
),
api
.
ReplaceNodesAdminUserApi
.
as_view
(),
name
=
'replace-nodes-admin-user'
),
url
(
r'^v1/admin-user/(?P<pk>[0-9a-zA-Z\-]{36})/auth/$'
,
url
(
r'^v1/admin-user/(?P<pk>[0-9a-zA-Z\-]{36})/auth/$'
,
...
...
apps/assets/urls/views_urls.py
View file @
722bf786
...
@@ -50,4 +50,3 @@ urlpatterns = [
...
@@ -50,4 +50,3 @@ urlpatterns = [
url
(
r'^domain/(?P<pk>[0-9a-zA-Z\-]{36})/gateway/create/$'
,
views
.
DomainGatewayCreateView
.
as_view
(),
name
=
'domain-gateway-create'
),
url
(
r'^domain/(?P<pk>[0-9a-zA-Z\-]{36})/gateway/create/$'
,
views
.
DomainGatewayCreateView
.
as_view
(),
name
=
'domain-gateway-create'
),
url
(
r'^domain/gateway/(?P<pk>[0-9a-zA-Z\-]{36})/update/$'
,
views
.
DomainGatewayUpdateView
.
as_view
(),
name
=
'domain-gateway-update'
),
url
(
r'^domain/gateway/(?P<pk>[0-9a-zA-Z\-]{36})/update/$'
,
views
.
DomainGatewayUpdateView
.
as_view
(),
name
=
'domain-gateway-update'
),
]
]
apps/assets/utils.py
View file @
722bf786
...
@@ -54,7 +54,8 @@ def test_gateway_connectability(gateway):
...
@@ -54,7 +54,8 @@ def test_gateway_connectability(gateway):
proxy
.
set_missing_host_key_policy
(
paramiko
.
AutoAddPolicy
())
proxy
.
set_missing_host_key_policy
(
paramiko
.
AutoAddPolicy
())
try
:
try
:
proxy
.
connect
(
gateway
.
ip
,
username
=
gateway
.
username
,
proxy
.
connect
(
gateway
.
ip
,
gateway
.
port
,
username
=
gateway
.
username
,
password
=
gateway
.
password
,
password
=
gateway
.
password
,
pkey
=
gateway
.
private_key_obj
)
pkey
=
gateway
.
private_key_obj
)
except
(
paramiko
.
AuthenticationException
,
except
(
paramiko
.
AuthenticationException
,
...
...
apps/assets/views/domain.py
View file @
722bf786
...
@@ -140,11 +140,6 @@ class DomainGatewayUpdateView(AdminUserRequiredMixin, UpdateView):
...
@@ -140,11 +140,6 @@ class DomainGatewayUpdateView(AdminUserRequiredMixin, UpdateView):
domain
=
self
.
object
.
domain
domain
=
self
.
object
.
domain
return
reverse
(
'assets:domain-gateway-list'
,
kwargs
=
{
"pk"
:
domain
.
id
})
return
reverse
(
'assets:domain-gateway-list'
,
kwargs
=
{
"pk"
:
domain
.
id
})
def
form_valid
(
self
,
form
):
response
=
super
()
.
form_valid
(
form
)
print
(
form
.
cleaned_data
)
return
response
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
context
=
{
'app'
:
_
(
'Assets'
),
'app'
:
_
(
'Assets'
),
...
...
apps/common/forms.py
View file @
722bf786
...
@@ -170,7 +170,7 @@ class TerminalSettingForm(BaseForm):
...
@@ -170,7 +170,7 @@ class TerminalSettingForm(BaseForm):
class
SecuritySettingForm
(
BaseForm
):
class
SecuritySettingForm
(
BaseForm
):
# MFA
全局设置
# MFA
global setting
SECURITY_MFA_AUTH
=
forms
.
BooleanField
(
SECURITY_MFA_AUTH
=
forms
.
BooleanField
(
initial
=
False
,
required
=
False
,
initial
=
False
,
required
=
False
,
label
=
_
(
"MFA Secondary certification"
),
label
=
_
(
"MFA Secondary certification"
),
...
@@ -179,12 +179,26 @@ class SecuritySettingForm(BaseForm):
...
@@ -179,12 +179,26 @@ class SecuritySettingForm(BaseForm):
'authentication (valid for all users, including administrators)'
'authentication (valid for all users, including administrators)'
)
)
)
)
# 最小长度
# limit login count
SECURITY_LOGIN_LIMIT_COUNT
=
forms
.
IntegerField
(
initial
=
3
,
min_value
=
3
,
label
=
_
(
"Limit the number of login failures"
)
)
# limit login time
SECURITY_LOGIN_LIMIT_TIME
=
forms
.
IntegerField
(
initial
=
30
,
min_value
=
5
,
label
=
_
(
"No logon interval"
),
help_text
=
_
(
"Tip :(unit/minute) if the user has failed to log in for a limited "
"number of times, no login is allowed during this time interval."
)
)
# min length
SECURITY_PASSWORD_MIN_LENGTH
=
forms
.
IntegerField
(
SECURITY_PASSWORD_MIN_LENGTH
=
forms
.
IntegerField
(
initial
=
6
,
label
=
_
(
"Password minimum length"
),
initial
=
6
,
label
=
_
(
"Password minimum length"
),
min_value
=
6
min_value
=
6
)
)
#
大写字母
#
upper case
SECURITY_PASSWORD_UPPER_CASE
=
forms
.
BooleanField
(
SECURITY_PASSWORD_UPPER_CASE
=
forms
.
BooleanField
(
initial
=
False
,
required
=
False
,
initial
=
False
,
required
=
False
,
...
@@ -193,21 +207,21 @@ class SecuritySettingForm(BaseForm):
...
@@ -193,21 +207,21 @@ class SecuritySettingForm(BaseForm):
'After opening, the user password changes '
'After opening, the user password changes '
'and resets must contain uppercase letters'
)
'and resets must contain uppercase letters'
)
)
)
#
小写字母
#
lower case
SECURITY_PASSWORD_LOWER_CASE
=
forms
.
BooleanField
(
SECURITY_PASSWORD_LOWER_CASE
=
forms
.
BooleanField
(
initial
=
False
,
required
=
False
,
initial
=
False
,
required
=
False
,
label
=
_
(
"Must contain lowercase letters"
),
label
=
_
(
"Must contain lowercase letters"
),
help_text
=
_
(
'After opening, the user password changes '
help_text
=
_
(
'After opening, the user password changes '
'and resets must contain lowercase letters'
)
'and resets must contain lowercase letters'
)
)
)
#
数字
#
number
SECURITY_PASSWORD_NUMBER
=
forms
.
BooleanField
(
SECURITY_PASSWORD_NUMBER
=
forms
.
BooleanField
(
initial
=
False
,
required
=
False
,
initial
=
False
,
required
=
False
,
label
=
_
(
"Must contain numeric characters"
),
label
=
_
(
"Must contain numeric characters"
),
help_text
=
_
(
'After opening, the user password changes '
help_text
=
_
(
'After opening, the user password changes '
'and resets must contain numeric characters'
)
'and resets must contain numeric characters'
)
)
)
#
特殊字符
#
special char
SECURITY_PASSWORD_SPECIAL_CHAR
=
forms
.
BooleanField
(
SECURITY_PASSWORD_SPECIAL_CHAR
=
forms
.
BooleanField
(
initial
=
False
,
required
=
False
,
initial
=
False
,
required
=
False
,
label
=
_
(
"Must contain special characters"
),
label
=
_
(
"Must contain special characters"
),
...
...
apps/common/templates/common/security_setting.html
View file @
722bf786
...
@@ -39,9 +39,9 @@
...
@@ -39,9 +39,9 @@
{% endif %}
{% endif %}
{% csrf_token %}
{% csrf_token %}
<h3>
{% trans "
MFA setting
" %}
</h3>
<h3>
{% trans "
User login settings
" %}
</h3>
{% for field in form %}
{% for field in form %}
{% if forloop.counter ==
2
%}
{% if forloop.counter ==
4
%}
<div
class=
"hr-line-dashed"
></div>
<div
class=
"hr-line-dashed"
></div>
<h3>
{% trans "Password check rule" %}
</h3>
<h3>
{% trans "Password check rule" %}
</h3>
{% endif %}
{% endif %}
...
...
apps/i18n/zh/LC_MESSAGES/django.mo
View file @
722bf786
No preview for this file type
apps/i18n/zh/LC_MESSAGES/django.po
View file @
722bf786
...
@@ -8,7 +8,7 @@ msgid ""
...
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
msgstr ""
"Project-Id-Version: Jumpserver 0.3.3\n"
"Project-Id-Version: Jumpserver 0.3.3\n"
"Report-Msgid-Bugs-To: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-0
6-07 11:34
+0800\n"
"POT-Creation-Date: 2018-0
7-13 19:20
+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: ibuler <ibuler@qq.com>\n"
"Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: Jumpserver team<ibuler@qq.com>\n"
"Language-Team: Jumpserver team<ibuler@qq.com>\n"
...
@@ -29,38 +29,38 @@ msgstr ""
...
@@ -29,38 +29,38 @@ msgstr ""
msgid "测试节点下资产是否可连接: {}"
msgid "测试节点下资产是否可连接: {}"
msgstr ""
msgstr ""
#: assets/forms/asset.py:24 assets/models/asset.py:
75 assets/models/user.py:103
#: assets/forms/asset.py:24 assets/models/asset.py:
89 assets/models/user.py:112
#: assets/templates/assets/asset_detail.html:183
#: assets/templates/assets/asset_detail.html:183
#: assets/templates/assets/asset_detail.html:191
#: assets/templates/assets/asset_detail.html:191
#: assets/templates/assets/system_user_detail.html:17
5
perms/models.py:33
#: assets/templates/assets/system_user_detail.html:17
8
perms/models.py:33
msgid "Nodes"
msgid "Nodes"
msgstr "节点管理"
msgstr "节点管理"
#: assets/forms/asset.py:27 assets/forms/asset.py:66 assets/forms/asset.py:109
#: assets/forms/asset.py:27 assets/forms/asset.py:66 assets/forms/asset.py:109
#: assets/forms/asset.py:113 assets/models/asset.py:
80
#: assets/forms/asset.py:113 assets/models/asset.py:
94
#: assets/models/cluster.py:19 assets/models/user.py:72
#: assets/models/cluster.py:19 assets/models/user.py:72
#: assets/templates/assets/asset_detail.html:73 templates/_nav.html:25
#: assets/templates/assets/asset_detail.html:73 templates/_nav.html:25
msgid "Admin user"
msgid "Admin user"
msgstr "管理用户"
msgstr "管理用户"
#: assets/forms/asset.py:30 assets/forms/asset.py:69 assets/forms/asset.py:125
#: assets/forms/asset.py:30 assets/forms/asset.py:69 assets/forms/asset.py:125
#: assets/templates/assets/asset_create.html:3
5
#: assets/templates/assets/asset_create.html:3
6
#: assets/templates/assets/asset_create.html:3
7
#: assets/templates/assets/asset_create.html:3
8
#: assets/templates/assets/asset_list.html:75
#: assets/templates/assets/asset_list.html:75
#: assets/templates/assets/asset_update.html:4
0
#: assets/templates/assets/asset_update.html:4
1
#: assets/templates/assets/asset_update.html:4
2
#: assets/templates/assets/asset_update.html:4
3
#: assets/templates/assets/user_asset_list.html:34
#: assets/templates/assets/user_asset_list.html:34
msgid "Label"
msgid "Label"
msgstr "标签"
msgstr "标签"
#: assets/forms/asset.py:34 assets/forms/asset.py:73 assets/models/asset.py:
71
#: assets/forms/asset.py:34 assets/forms/asset.py:73 assets/models/asset.py:
85
#: assets/models/domain.py:46
#: assets/models/domain.py:46
msgid "Domain"
msgid "Domain"
msgstr "网域"
msgstr "网域"
#: assets/forms/asset.py:38 assets/forms/asset.py:63 assets/forms/asset.py:77
#: assets/forms/asset.py:38 assets/forms/asset.py:63 assets/forms/asset.py:77
#: assets/forms/asset.py:128 assets/templates/assets/asset_create.html:
29
#: assets/forms/asset.py:128 assets/templates/assets/asset_create.html:
30
#: assets/templates/assets/asset_update.html:3
4
perms/forms.py:40
#: assets/templates/assets/asset_update.html:3
5
perms/forms.py:40
#: perms/forms.py:47 perms/models.py:76
#: perms/forms.py:47 perms/models.py:76
#: perms/templates/perms/asset_permission_list.html:57
#: perms/templates/perms/asset_permission_list.html:57
#: perms/templates/perms/asset_permission_list.html:142
#: perms/templates/perms/asset_permission_list.html:142
...
@@ -90,7 +90,7 @@ msgstr "如果有多个的互相隔离的网络,设置资产属于的网域,
...
@@ -90,7 +90,7 @@ msgstr "如果有多个的互相隔离的网络,设置资产属于的网域,
msgid "Select assets"
msgid "Select assets"
msgstr "选择资产"
msgstr "选择资产"
#: assets/forms/asset.py:105 assets/models/asset.py:
67
#: assets/forms/asset.py:105 assets/models/asset.py:
81
#: assets/models/domain.py:44 assets/templates/assets/admin_user_assets.html:53
#: assets/models/domain.py:44 assets/templates/assets/admin_user_assets.html:53
#: assets/templates/assets/asset_detail.html:69
#: assets/templates/assets/asset_detail.html:69
#: assets/templates/assets/domain_gateway_list.html:58
#: assets/templates/assets/domain_gateway_list.html:58
...
@@ -99,11 +99,11 @@ msgid "Port"
...
@@ -99,11 +99,11 @@ msgid "Port"
msgstr "端口"
msgstr "端口"
#: assets/forms/domain.py:14 assets/forms/label.py:13
#: assets/forms/domain.py:14 assets/forms/label.py:13
#: assets/models/asset.py:2
23
assets/templates/assets/admin_user_list.html:25
#: assets/models/asset.py:2
37
assets/templates/assets/admin_user_list.html:25
#: assets/templates/assets/domain_detail.html:60
#: assets/templates/assets/domain_detail.html:60
#: assets/templates/assets/domain_list.html:
15
#: assets/templates/assets/domain_list.html:
23
#: assets/templates/assets/label_list.html:16
#: assets/templates/assets/label_list.html:16
#: assets/templates/assets/system_user_list.html:
29
audits/models.py:11
#: assets/templates/assets/system_user_list.html:
30
audits/models.py:11
#: audits/templates/audits/ftp_log_list.html:41
#: audits/templates/audits/ftp_log_list.html:41
#: audits/templates/audits/ftp_log_list.html:72 perms/forms.py:37
#: audits/templates/audits/ftp_log_list.html:72 perms/forms.py:37
#: perms/models.py:32
#: perms/models.py:32
...
@@ -118,14 +118,14 @@ msgstr "端口"
...
@@ -118,14 +118,14 @@ msgstr "端口"
msgid "Asset"
msgid "Asset"
msgstr "资产"
msgstr "资产"
#: assets/forms/domain.py:54 assets/forms/user.py:79 assets/forms/user.py:1
20
#: assets/forms/domain.py:54 assets/forms/user.py:79 assets/forms/user.py:1
39
#: assets/models/base.py:21 assets/models/cluster.py:18
#: assets/models/base.py:21 assets/models/cluster.py:18
#: assets/models/domain.py:17 assets/models/group.py:20
#: assets/models/domain.py:17 assets/models/group.py:20
#: assets/models/label.py:17 assets/templates/assets/admin_user_detail.html:56
#: assets/models/label.py:17 assets/templates/assets/admin_user_detail.html:56
#: assets/templates/assets/admin_user_list.html:23
#: assets/templates/assets/admin_user_list.html:23
#: assets/templates/assets/domain_detail.html:56
#: assets/templates/assets/domain_detail.html:56
#: assets/templates/assets/domain_gateway_list.html:56
#: assets/templates/assets/domain_gateway_list.html:56
#: assets/templates/assets/domain_list.html:
14
#: assets/templates/assets/domain_list.html:
22
#: assets/templates/assets/label_list.html:14
#: assets/templates/assets/label_list.html:14
#: assets/templates/assets/system_user_detail.html:58
#: assets/templates/assets/system_user_detail.html:58
#: assets/templates/assets/system_user_list.html:26 common/models.py:26
#: assets/templates/assets/system_user_list.html:26 common/models.py:26
...
@@ -147,16 +147,16 @@ msgstr "资产"
...
@@ -147,16 +147,16 @@ msgstr "资产"
msgid "Name"
msgid "Name"
msgstr "名称"
msgstr "名称"
#: assets/forms/domain.py:55 assets/forms/user.py:80 assets/forms/user.py:1
21
#: assets/forms/domain.py:55 assets/forms/user.py:80 assets/forms/user.py:1
40
#: assets/models/base.py:22 assets/templates/assets/admin_user_detail.html:60
#: assets/models/base.py:22 assets/templates/assets/admin_user_detail.html:60
#: assets/templates/assets/admin_user_list.html:24
#: assets/templates/assets/admin_user_list.html:24
#: assets/templates/assets/domain_gateway_list.html:60
#: assets/templates/assets/domain_gateway_list.html:60
#: assets/templates/assets/system_user_detail.html:62
#: assets/templates/assets/system_user_detail.html:62
#: assets/templates/assets/system_user_list.html:27
#: assets/templates/assets/system_user_list.html:27
#: perms/templates/perms/asset_permission_user.html:55 users/forms.py:13
#: perms/templates/perms/asset_permission_user.html:55 users/forms.py:13
#: users/forms.py:
21 users/forms.py:30 users/models/authentication.py:45
#: users/forms.py:
31 users/models/authentication.py:70 users/models/user.py:47
#: users/
models/user.py:47 users/
templates/users/_select_user_modal.html:14
#: users/templates/users/_select_user_modal.html:14
#: users/templates/users/login.html:
56
#: users/templates/users/login.html:
60
#: users/templates/users/login_log_list.html:49
#: users/templates/users/login_log_list.html:49
#: users/templates/users/user_detail.html:67
#: users/templates/users/user_detail.html:67
#: users/templates/users/user_list.html:24
#: users/templates/users/user_list.html:24
...
@@ -169,8 +169,8 @@ msgid "Password or private key passphrase"
...
@@ -169,8 +169,8 @@ msgid "Password or private key passphrase"
msgstr "密码或密钥密码"
msgstr "密码或密钥密码"
#: assets/forms/user.py:25 assets/models/base.py:23 common/forms.py:113
#: assets/forms/user.py:25 assets/models/base.py:23 common/forms.py:113
#: users/forms.py:15 users/forms.py:
23 users/forms.py:32 users/forms.py:44
#: users/forms.py:15 users/forms.py:
33 users/forms.py:45
#: users/templates/users/login.html:
59
#: users/templates/users/login.html:
63
#: users/templates/users/reset_password.html:53
#: users/templates/users/reset_password.html:53
#: users/templates/users/user_create.html:10
#: users/templates/users/user_create.html:10
#: users/templates/users/user_password_authentication.html:14
#: users/templates/users/user_password_authentication.html:14
...
@@ -192,17 +192,27 @@ msgstr "ssh密钥不合法"
...
@@ -192,17 +192,27 @@ msgstr "ssh密钥不合法"
msgid "Password and private key file must be input one"
msgid "Password and private key file must be input one"
msgstr "密码和私钥, 必须输入一个"
msgstr "密码和私钥, 必须输入一个"
#: assets/forms/user.py:126
#: assets/forms/user.py:125
msgid "* Automatic login mode, must fill in the username."
msgstr "自动登录模式,必须填写用户名"
#: assets/forms/user.py:145
msgid "Auto push system user to asset"
msgid "Auto push system user to asset"
msgstr "自动推送系统用户到资产"
msgstr "自动推送系统用户到资产"
#: assets/forms/user.py:1
27
#: assets/forms/user.py:1
46
msgid ""
msgid ""
"High level will be using login asset as default, if user was granted more "
"High level will be using login asset as default, if user was granted more "
"than 2 system user"
"than 2 system user"
msgstr "高优先级的系统用户将会作为默认登录用户"
msgstr "高优先级的系统用户将会作为默认登录用户"
#: assets/models/asset.py:63 assets/models/domain.py:43
#: assets/forms/user.py:148
msgid ""
"If you choose manual login mode, you do not need to fill in the username and "
"password."
msgstr "如果选择手动登录模式,用户名和密码则不需要填写"
#: assets/models/asset.py:74 assets/models/domain.py:43
#: assets/templates/assets/_asset_list_modal.html:46
#: assets/templates/assets/_asset_list_modal.html:46
#: assets/templates/assets/admin_user_assets.html:52
#: assets/templates/assets/admin_user_assets.html:52
#: assets/templates/assets/asset_detail.html:61
#: assets/templates/assets/asset_detail.html:61
...
@@ -217,7 +227,7 @@ msgstr "高优先级的系统用户将会作为默认登录用户"
...
@@ -217,7 +227,7 @@ msgstr "高优先级的系统用户将会作为默认登录用户"
msgid "IP"
msgid "IP"
msgstr "IP"
msgstr "IP"
#: assets/models/asset.py:
66
assets/templates/assets/_asset_list_modal.html:45
#: assets/models/asset.py:
77
assets/templates/assets/_asset_list_modal.html:45
#: assets/templates/assets/admin_user_assets.html:51
#: assets/templates/assets/admin_user_assets.html:51
#: assets/templates/assets/asset_detail.html:57
#: assets/templates/assets/asset_detail.html:57
#: assets/templates/assets/asset_list.html:86
#: assets/templates/assets/asset_list.html:86
...
@@ -229,98 +239,107 @@ msgstr "IP"
...
@@ -229,98 +239,107 @@ msgstr "IP"
msgid "Hostname"
msgid "Hostname"
msgstr "主机名"
msgstr "主机名"
#: assets/models/asset.py:69 assets/templates/assets/asset_detail.html:97
#: assets/models/asset.py:80 assets/models/domain.py:45
#: assets/models/user.py:115
#: assets/templates/assets/domain_gateway_list.html:59
#: assets/templates/assets/system_user_detail.html:70
#: assets/templates/assets/system_user_list.html:28
#: terminal/templates/terminal/session_list.html:75
msgid "Protocol"
msgstr "协议"
#: assets/models/asset.py:83 assets/templates/assets/asset_detail.html:97
msgid "Platform"
msgid "Platform"
msgstr "系统平台"
msgstr "系统平台"
#: assets/models/asset.py:
76
assets/models/domain.py:48
#: assets/models/asset.py:
90
assets/models/domain.py:48
#: assets/models/label.py:20 assets/templates/assets/asset_detail.html:105
#: assets/models/label.py:20 assets/templates/assets/asset_detail.html:105
msgid "Is active"
msgid "Is active"
msgstr "激活"
msgstr "激活"
#: assets/models/asset.py:
85
assets/templates/assets/asset_detail.html:65
#: assets/models/asset.py:
99
assets/templates/assets/asset_detail.html:65
msgid "Public IP"
msgid "Public IP"
msgstr "公网IP"
msgstr "公网IP"
#: assets/models/asset.py:
87
assets/templates/assets/asset_detail.html:113
#: assets/models/asset.py:
101
assets/templates/assets/asset_detail.html:113
msgid "Asset number"
msgid "Asset number"
msgstr "资产编号"
msgstr "资产编号"
#: assets/models/asset.py:
91
assets/templates/assets/asset_detail.html:77
#: assets/models/asset.py:
105
assets/templates/assets/asset_detail.html:77
msgid "Vendor"
msgid "Vendor"
msgstr "制造商"
msgstr "制造商"
#: assets/models/asset.py:
93
assets/templates/assets/asset_detail.html:81
#: assets/models/asset.py:
107
assets/templates/assets/asset_detail.html:81
msgid "Model"
msgid "Model"
msgstr "型号"
msgstr "型号"
#: assets/models/asset.py:
95
assets/templates/assets/asset_detail.html:109
#: assets/models/asset.py:
109
assets/templates/assets/asset_detail.html:109
msgid "Serial number"
msgid "Serial number"
msgstr "序列号"
msgstr "序列号"
#: assets/models/asset.py:
98
#: assets/models/asset.py:
112
msgid "CPU model"
msgid "CPU model"
msgstr "CPU型号"
msgstr "CPU型号"
#: assets/models/asset.py:
99
#: assets/models/asset.py:
113
msgid "CPU count"
msgid "CPU count"
msgstr "CPU数量"
msgstr "CPU数量"
#: assets/models/asset.py:1
00
#: assets/models/asset.py:1
14
msgid "CPU cores"
msgid "CPU cores"
msgstr "CPU核数"
msgstr "CPU核数"
#: assets/models/asset.py:1
02
assets/templates/assets/asset_detail.html:89
#: assets/models/asset.py:1
16
assets/templates/assets/asset_detail.html:89
msgid "Memory"
msgid "Memory"
msgstr "内存"
msgstr "内存"
#: assets/models/asset.py:1
04
#: assets/models/asset.py:1
18
msgid "Disk total"
msgid "Disk total"
msgstr "硬盘大小"
msgstr "硬盘大小"
#: assets/models/asset.py:1
06
#: assets/models/asset.py:1
20
msgid "Disk info"
msgid "Disk info"
msgstr "硬盘信息"
msgstr "硬盘信息"
#: assets/models/asset.py:1
09
assets/templates/assets/asset_detail.html:101
#: assets/models/asset.py:1
23
assets/templates/assets/asset_detail.html:101
msgid "OS"
msgid "OS"
msgstr "操作系统"
msgstr "操作系统"
#: assets/models/asset.py:1
11
#: assets/models/asset.py:1
25
msgid "OS version"
msgid "OS version"
msgstr "系统版本"
msgstr "系统版本"
#: assets/models/asset.py:1
13
#: assets/models/asset.py:1
27
msgid "OS arch"
msgid "OS arch"
msgstr "系统架构"
msgstr "系统架构"
#: assets/models/asset.py:1
15
#: assets/models/asset.py:1
29
msgid "Hostname raw"
msgid "Hostname raw"
msgstr "主机名原始"
msgstr "主机名原始"
#: assets/models/asset.py:1
19 assets/templates/assets/asset_create.html:33
#: assets/models/asset.py:1
33 assets/templates/assets/asset_create.html:34
#: assets/templates/assets/asset_detail.html:220
#: assets/templates/assets/asset_detail.html:220
#: assets/templates/assets/asset_update.html:3
8
templates/_nav.html:27
#: assets/templates/assets/asset_update.html:3
9
templates/_nav.html:27
msgid "Labels"
msgid "Labels"
msgstr "标签管理"
msgstr "标签管理"
#: assets/models/asset.py:1
21
assets/models/base.py:29
#: assets/models/asset.py:1
35
assets/models/base.py:29
#: assets/models/cluster.py:28 assets/models/group.py:21
#: assets/models/cluster.py:28 assets/models/group.py:21
#: assets/templates/assets/admin_user_detail.html:68
#: assets/templates/assets/admin_user_detail.html:68
#: assets/templates/assets/asset_detail.html:117
#: assets/templates/assets/asset_detail.html:117
#: assets/templates/assets/domain_detail.html:72
#: assets/templates/assets/domain_detail.html:72
#: assets/templates/assets/system_user_detail.html:
96
#: assets/templates/assets/system_user_detail.html:
100
#: ops/templates/ops/adhoc_detail.html:86 perms/models.py:38 perms/models.py:81
#: ops/templates/ops/adhoc_detail.html:86 perms/models.py:38 perms/models.py:81
#: perms/templates/perms/asset_permission_detail.html:98
#: perms/templates/perms/asset_permission_detail.html:98
#: users/models/user.py:90 users/templates/users/user_detail.html:111
#: users/models/user.py:90 users/templates/users/user_detail.html:111
msgid "Created by"
msgid "Created by"
msgstr "创建者"
msgstr "创建者"
#: assets/models/asset.py:1
24
assets/models/cluster.py:26
#: assets/models/asset.py:1
38
assets/models/cluster.py:26
#: assets/models/domain.py:20 assets/models/group.py:22
#: assets/models/domain.py:20 assets/models/group.py:22
#: assets/models/label.py:23 assets/templates/assets/admin_user_detail.html:64
#: assets/models/label.py:23 assets/templates/assets/admin_user_detail.html:64
#: assets/templates/assets/domain_detail.html:68
#: assets/templates/assets/domain_detail.html:68
#: assets/templates/assets/system_user_detail.html:9
2
#: assets/templates/assets/system_user_detail.html:9
6
#: ops/templates/ops/adhoc_detail.html:90 ops/templates/ops/task_detail.html:63
#: ops/templates/ops/adhoc_detail.html:90 ops/templates/ops/task_detail.html:63
#: perms/models.py:39 perms/models.py:82
#: perms/models.py:39 perms/models.py:82
#: perms/templates/perms/asset_permission_detail.html:94
#: perms/templates/perms/asset_permission_detail.html:94
...
@@ -329,7 +348,7 @@ msgstr "创建者"
...
@@ -329,7 +348,7 @@ msgstr "创建者"
msgid "Date created"
msgid "Date created"
msgstr "创建日期"
msgstr "创建日期"
#: assets/models/asset.py:1
26
assets/models/base.py:26
#: assets/models/asset.py:1
40
assets/models/base.py:26
#: assets/models/cluster.py:29 assets/models/domain.py:18
#: assets/models/cluster.py:29 assets/models/domain.py:18
#: assets/models/domain.py:47 assets/models/group.py:23
#: assets/models/domain.py:47 assets/models/group.py:23
#: assets/models/label.py:21 assets/templates/assets/admin_user_detail.html:72
#: assets/models/label.py:21 assets/templates/assets/admin_user_detail.html:72
...
@@ -337,9 +356,9 @@ msgstr "创建日期"
...
@@ -337,9 +356,9 @@ msgstr "创建日期"
#: assets/templates/assets/asset_detail.html:125
#: assets/templates/assets/asset_detail.html:125
#: assets/templates/assets/domain_detail.html:76
#: assets/templates/assets/domain_detail.html:76
#: assets/templates/assets/domain_gateway_list.html:61
#: assets/templates/assets/domain_gateway_list.html:61
#: assets/templates/assets/domain_list.html:
17
#: assets/templates/assets/domain_list.html:
25
#: assets/templates/assets/system_user_detail.html:10
0
#: assets/templates/assets/system_user_detail.html:10
4
#: assets/templates/assets/system_user_list.html:3
3
common/models.py:30
#: assets/templates/assets/system_user_list.html:3
4
common/models.py:30
#: ops/models/adhoc.py:42 perms/models.py:40 perms/models.py:83
#: ops/models/adhoc.py:42 perms/models.py:40 perms/models.py:83
#: perms/templates/perms/asset_permission_detail.html:102 terminal/models.py:26
#: perms/templates/perms/asset_permission_detail.html:102 terminal/models.py:26
#: terminal/templates/terminal/terminal_detail.html:63 users/models/group.py:13
#: terminal/templates/terminal/terminal_detail.html:63 users/models/group.py:13
...
@@ -392,7 +411,7 @@ msgid "Default"
...
@@ -392,7 +411,7 @@ msgid "Default"
msgstr "默认"
msgstr "默认"
#: assets/models/cluster.py:36 assets/models/label.py:13
#: assets/models/cluster.py:36 assets/models/label.py:13
#: users/models/user.py:34
3
#: users/models/user.py:34
5
msgid "System"
msgid "System"
msgstr "系统"
msgstr "系统"
...
@@ -404,14 +423,6 @@ msgstr "默认Cluster"
...
@@ -404,14 +423,6 @@ msgstr "默认Cluster"
msgid "Cluster"
msgid "Cluster"
msgstr "集群"
msgstr "集群"
#: assets/models/domain.py:45 assets/models/user.py:106
#: assets/templates/assets/domain_gateway_list.html:59
#: assets/templates/assets/system_user_detail.html:66
#: assets/templates/assets/system_user_list.html:28
#: terminal/templates/terminal/session_list.html:75
msgid "Protocol"
msgstr "协议"
#: assets/models/group.py:30
#: assets/models/group.py:30
msgid "Asset group"
msgid "Asset group"
msgstr "资产组"
msgstr "资产组"
...
@@ -431,10 +442,10 @@ msgstr "默认资产组"
...
@@ -431,10 +442,10 @@ msgstr "默认资产组"
#: terminal/templates/terminal/command_list.html:32
#: terminal/templates/terminal/command_list.html:32
#: terminal/templates/terminal/command_list.html:72
#: terminal/templates/terminal/command_list.html:72
#: terminal/templates/terminal/session_list.html:33
#: terminal/templates/terminal/session_list.html:33
#: terminal/templates/terminal/session_list.html:71 users/forms.py:28
1
#: terminal/templates/terminal/session_list.html:71 users/forms.py:28
2
#: users/models/user.py:31 users/models/user.py:33
1
#: users/models/user.py:31 users/models/user.py:33
3
#: users/templates/users/user_group_detail.html:78
#: users/templates/users/user_group_detail.html:78
#: users/templates/users/user_group_list.html:13 users/views/user.py:36
2
#: users/templates/users/user_group_list.html:13 users/views/user.py:36
1
msgid "User"
msgid "User"
msgstr "用户"
msgstr "用户"
...
@@ -451,7 +462,15 @@ msgstr "分类"
...
@@ -451,7 +462,15 @@ msgstr "分类"
msgid "Key"
msgid "Key"
msgstr ""
msgstr ""
#: assets/models/user.py:104
#: assets/models/user.py:108
msgid "Automatic login"
msgstr "自动登录"
#: assets/models/user.py:109
msgid "Manually login"
msgstr "手动登录"
#: assets/models/user.py:113
#: assets/templates/assets/_asset_group_bulk_update_modal.html:11
#: assets/templates/assets/_asset_group_bulk_update_modal.html:11
#: assets/templates/assets/system_user_asset.html:21
#: assets/templates/assets/system_user_asset.html:21
#: assets/views/admin_user.py:29 assets/views/admin_user.py:47
#: assets/views/admin_user.py:29 assets/views/admin_user.py:47
...
@@ -461,7 +480,7 @@ msgstr ""
...
@@ -461,7 +480,7 @@ msgstr ""
#: assets/views/asset.py:197 assets/views/domain.py:29
#: assets/views/asset.py:197 assets/views/domain.py:29
#: assets/views/domain.py:45 assets/views/domain.py:61
#: assets/views/domain.py:45 assets/views/domain.py:61
#: assets/views/domain.py:74 assets/views/domain.py:98
#: assets/views/domain.py:74 assets/views/domain.py:98
#: assets/views/domain.py:126 assets/views/domain.py:1
50
#: assets/views/domain.py:126 assets/views/domain.py:1
45
#: assets/views/label.py:26 assets/views/label.py:42 assets/views/label.py:58
#: assets/views/label.py:26 assets/views/label.py:42 assets/views/label.py:58
#: assets/views/system_user.py:28 assets/views/system_user.py:44
#: assets/views/system_user.py:28 assets/views/system_user.py:44
#: assets/views/system_user.py:60 assets/views/system_user.py:74
#: assets/views/system_user.py:60 assets/views/system_user.py:74
...
@@ -469,25 +488,30 @@ msgstr ""
...
@@ -469,25 +488,30 @@ msgstr ""
msgid "Assets"
msgid "Assets"
msgstr "资产管理"
msgstr "资产管理"
#: assets/models/user.py:1
05
#: assets/models/user.py:1
14
msgid "Priority"
msgid "Priority"
msgstr "优先级"
msgstr "优先级"
#: assets/models/user.py:1
07 assets/templates/assets/_system_user.html:58
#: assets/models/user.py:1
16 assets/templates/assets/_system_user.html:59
#: assets/templates/assets/system_user_detail.html:1
18
#: assets/templates/assets/system_user_detail.html:1
22
#: assets/templates/assets/system_user_update.html:1
1
#: assets/templates/assets/system_user_update.html:1
0
msgid "Auto push"
msgid "Auto push"
msgstr "自动推送"
msgstr "自动推送"
#: assets/models/user.py:1
08 assets/templates/assets/system_user_detail.html:70
#: assets/models/user.py:1
17 assets/templates/assets/system_user_detail.html:74
msgid "Sudo"
msgid "Sudo"
msgstr "Sudo"
msgstr "Sudo"
#: assets/models/user.py:1
09 assets/templates/assets/system_user_detail.html:75
#: assets/models/user.py:1
18 assets/templates/assets/system_user_detail.html:79
msgid "Shell"
msgid "Shell"
msgstr "Shell"
msgstr "Shell"
#: assets/models/user.py:149 audits/models.py:12
#: assets/models/user.py:119 assets/templates/assets/system_user_detail.html:66
#: assets/templates/assets/system_user_list.html:29
msgid "Login mode"
msgstr "登录模式"
#: assets/models/user.py:159 audits/models.py:12
#: audits/templates/audits/ftp_log_list.html:49
#: audits/templates/audits/ftp_log_list.html:49
#: audits/templates/audits/ftp_log_list.html:73 perms/forms.py:43
#: audits/templates/audits/ftp_log_list.html:73 perms/forms.py:43
#: perms/models.py:34 perms/models.py:78
#: perms/models.py:34 perms/models.py:78
...
@@ -601,32 +625,31 @@ msgid "Basic"
...
@@ -601,32 +625,31 @@ msgid "Basic"
msgstr "基本"
msgstr "基本"
#: assets/templates/assets/_system_user.html:44
#: assets/templates/assets/_system_user.html:44
#: assets/templates/assets/asset_create.html:2
5
#: assets/templates/assets/asset_create.html:2
6
#: assets/templates/assets/asset_update.html:3
0
#: assets/templates/assets/asset_update.html:3
1
#: assets/templates/assets/gateway_create_update.html:45
#: assets/templates/assets/gateway_create_update.html:45
#: assets/templates/assets/system_user_update.html:7
#: users/templates/users/_user.html:21
#: users/templates/users/_user.html:21
msgid "Auth"
msgid "Auth"
msgstr "认证"
msgstr "认证"
#: assets/templates/assets/_system_user.html:4
7
#: assets/templates/assets/_system_user.html:4
8
msgid "Auto generate key"
msgid "Auto generate key"
msgstr "自动生成密钥"
msgstr "自动生成密钥"
#: assets/templates/assets/_system_user.html:6
4
#: assets/templates/assets/_system_user.html:6
5
#: assets/templates/assets/asset_create.html:
59
#: assets/templates/assets/asset_create.html:
60
#: assets/templates/assets/asset_update.html:6
3
#: assets/templates/assets/asset_update.html:6
4
#: assets/templates/assets/gateway_create_update.html:53
#: assets/templates/assets/gateway_create_update.html:53
#: perms/templates/perms/asset_permission_create_update.html:45
#: perms/templates/perms/asset_permission_create_update.html:45
#: terminal/templates/terminal/terminal_update.html:42
#: terminal/templates/terminal/terminal_update.html:42
msgid "Other"
msgid "Other"
msgstr "其它"
msgstr "其它"
#: assets/templates/assets/_system_user.html:7
0
#: assets/templates/assets/_system_user.html:7
1
#: assets/templates/assets/admin_user_create_update.html:45
#: assets/templates/assets/admin_user_create_update.html:45
#: assets/templates/assets/asset_bulk_update.html:23
#: assets/templates/assets/asset_bulk_update.html:23
#: assets/templates/assets/asset_create.html:6
6
#: assets/templates/assets/asset_create.html:6
7
#: assets/templates/assets/asset_update.html:7
0
#: assets/templates/assets/asset_update.html:7
1
#: assets/templates/assets/domain_create_update.html:16
#: assets/templates/assets/domain_create_update.html:16
#: assets/templates/assets/gateway_create_update.html:58
#: assets/templates/assets/gateway_create_update.html:58
#: assets/templates/assets/label_create_update.html:18
#: assets/templates/assets/label_create_update.html:18
...
@@ -647,12 +670,12 @@ msgstr "其它"
...
@@ -647,12 +670,12 @@ msgstr "其它"
msgid "Reset"
msgid "Reset"
msgstr "重置"
msgstr "重置"
#: assets/templates/assets/_system_user.html:7
1
#: assets/templates/assets/_system_user.html:7
2
#: assets/templates/assets/admin_user_create_update.html:46
#: assets/templates/assets/admin_user_create_update.html:46
#: assets/templates/assets/asset_bulk_update.html:24
#: assets/templates/assets/asset_bulk_update.html:24
#: assets/templates/assets/asset_create.html:6
7
#: assets/templates/assets/asset_create.html:6
8
#: assets/templates/assets/asset_list.html:108
#: assets/templates/assets/asset_list.html:108
#: assets/templates/assets/asset_update.html:7
1
#: assets/templates/assets/asset_update.html:7
2
#: assets/templates/assets/domain_create_update.html:17
#: assets/templates/assets/domain_create_update.html:17
#: assets/templates/assets/gateway_create_update.html:59
#: assets/templates/assets/gateway_create_update.html:59
#: assets/templates/assets/label_create_update.html:19
#: assets/templates/assets/label_create_update.html:19
...
@@ -662,7 +685,7 @@ msgstr "重置"
...
@@ -662,7 +685,7 @@ msgstr "重置"
#: common/templates/common/security_setting.html:71
#: common/templates/common/security_setting.html:71
#: common/templates/common/terminal_setting.html:108
#: common/templates/common/terminal_setting.html:108
#: perms/templates/perms/asset_permission_create_update.html:70
#: perms/templates/perms/asset_permission_create_update.html:70
#: terminal/templates/terminal/session_list.html:12
4
#: terminal/templates/terminal/session_list.html:12
6
#: terminal/templates/terminal/terminal_update.html:48
#: terminal/templates/terminal/terminal_update.html:48
#: users/templates/users/_user.html:47
#: users/templates/users/_user.html:47
#: users/templates/users/forgot_password.html:44
#: users/templates/users/forgot_password.html:44
...
@@ -702,14 +725,14 @@ msgstr "资产列表"
...
@@ -702,14 +725,14 @@ msgstr "资产列表"
#: assets/templates/assets/admin_user_assets.html:54
#: assets/templates/assets/admin_user_assets.html:54
#: assets/templates/assets/admin_user_list.html:26
#: assets/templates/assets/admin_user_list.html:26
#: assets/templates/assets/system_user_asset.html:52
#: assets/templates/assets/system_user_asset.html:52
#: assets/templates/assets/system_user_list.html:3
0
#: assets/templates/assets/system_user_list.html:3
1
#: users/templates/users/user_group_granted_asset.html:47
#: users/templates/users/user_group_granted_asset.html:47
msgid "Reachable"
msgid "Reachable"
msgstr "可连接"
msgstr "可连接"
#: assets/templates/assets/admin_user_assets.html:66
#: assets/templates/assets/admin_user_assets.html:66
#: assets/templates/assets/system_user_asset.html:64
#: assets/templates/assets/system_user_asset.html:64
#: assets/templates/assets/system_user_detail.html:11
2
#: assets/templates/assets/system_user_detail.html:11
6
#: perms/templates/perms/asset_permission_detail.html:114
#: perms/templates/perms/asset_permission_detail.html:114
msgid "Quick update"
msgid "Quick update"
msgstr "快速更新"
msgstr "快速更新"
...
@@ -722,7 +745,7 @@ msgstr "测试可连接性"
...
@@ -722,7 +745,7 @@ msgstr "测试可连接性"
#: assets/templates/assets/admin_user_assets.html:75
#: assets/templates/assets/admin_user_assets.html:75
#: assets/templates/assets/asset_detail.html:171
#: assets/templates/assets/asset_detail.html:171
#: assets/templates/assets/system_user_asset.html:81
#: assets/templates/assets/system_user_asset.html:81
#: assets/templates/assets/system_user_detail.html:1
47
#: assets/templates/assets/system_user_detail.html:1
51
msgid "Test"
msgid "Test"
msgstr "测试"
msgstr "测试"
...
@@ -733,10 +756,10 @@ msgstr "测试"
...
@@ -733,10 +756,10 @@ msgstr "测试"
#: assets/templates/assets/domain_detail.html:24
#: assets/templates/assets/domain_detail.html:24
#: assets/templates/assets/domain_detail.html:103
#: assets/templates/assets/domain_detail.html:103
#: assets/templates/assets/domain_gateway_list.html:85
#: assets/templates/assets/domain_gateway_list.html:85
#: assets/templates/assets/domain_list.html:
42
#: assets/templates/assets/domain_list.html:
50
#: assets/templates/assets/label_list.html:38
#: assets/templates/assets/label_list.html:38
#: assets/templates/assets/system_user_detail.html:26
#: assets/templates/assets/system_user_detail.html:26
#: assets/templates/assets/system_user_list.html:8
8
#: assets/templates/assets/system_user_list.html:8
9
#: perms/templates/perms/asset_permission_detail.html:30
#: perms/templates/perms/asset_permission_detail.html:30
#: perms/templates/perms/asset_permission_list.html:191
#: perms/templates/perms/asset_permission_list.html:191
#: terminal/templates/terminal/terminal_detail.html:16
#: terminal/templates/terminal/terminal_detail.html:16
...
@@ -757,10 +780,10 @@ msgstr "更新"
...
@@ -757,10 +780,10 @@ msgstr "更新"
#: assets/templates/assets/domain_detail.html:28
#: assets/templates/assets/domain_detail.html:28
#: assets/templates/assets/domain_detail.html:104
#: assets/templates/assets/domain_detail.html:104
#: assets/templates/assets/domain_gateway_list.html:86
#: assets/templates/assets/domain_gateway_list.html:86
#: assets/templates/assets/domain_list.html:
43
#: assets/templates/assets/domain_list.html:
51
#: assets/templates/assets/label_list.html:39
#: assets/templates/assets/label_list.html:39
#: assets/templates/assets/system_user_detail.html:30
#: assets/templates/assets/system_user_detail.html:30
#: assets/templates/assets/system_user_list.html:
89
#: assets/templates/assets/system_user_list.html:
90
#: ops/templates/ops/task_list.html:72
#: ops/templates/ops/task_list.html:72
#: perms/templates/perms/asset_permission_detail.html:34
#: perms/templates/perms/asset_permission_detail.html:34
#: perms/templates/perms/asset_permission_list.html:192
#: perms/templates/perms/asset_permission_list.html:192
...
@@ -785,12 +808,13 @@ msgstr "选择节点"
...
@@ -785,12 +808,13 @@ msgstr "选择节点"
#: assets/templates/assets/admin_user_detail.html:100
#: assets/templates/assets/admin_user_detail.html:100
#: assets/templates/assets/asset_detail.html:200
#: assets/templates/assets/asset_detail.html:200
#: assets/templates/assets/asset_list.html:638
#: assets/templates/assets/asset_list.html:638
#: assets/templates/assets/system_user_detail.html:19
2
#: assets/templates/assets/system_user_detail.html:19
5
#: assets/templates/assets/system_user_list.html:13
8
templates/_modal.html:22
#: assets/templates/assets/system_user_list.html:13
9
templates/_modal.html:22
#: terminal/templates/terminal/session_detail.html:108
#: terminal/templates/terminal/session_detail.html:108
#: users/templates/users/user_detail.html:366
#: users/templates/users/user_detail.html:374
#: users/templates/users/user_detail.html:391
#: users/templates/users/user_detail.html:399
#: users/templates/users/user_detail.html:414
#: users/templates/users/user_detail.html:422
#: users/templates/users/user_detail.html:458
#: users/templates/users/user_group_create_update.html:32
#: users/templates/users/user_group_create_update.html:32
#: users/templates/users/user_group_list.html:86
#: users/templates/users/user_group_list.html:86
#: users/templates/users/user_list.html:200
#: users/templates/users/user_list.html:200
...
@@ -804,12 +828,12 @@ msgid "Create admin user"
...
@@ -804,12 +828,12 @@ msgid "Create admin user"
msgstr "创建管理用户"
msgstr "创建管理用户"
#: assets/templates/assets/admin_user_list.html:27
#: assets/templates/assets/admin_user_list.html:27
#: assets/templates/assets/system_user_list.html:3
1
#: assets/templates/assets/system_user_list.html:3
2
msgid "Unreachable"
msgid "Unreachable"
msgstr "不可达"
msgstr "不可达"
#: assets/templates/assets/admin_user_list.html:28
#: assets/templates/assets/admin_user_list.html:28
#: assets/templates/assets/system_user_list.html:3
2
#: assets/templates/assets/system_user_list.html:3
3
#: ops/templates/ops/adhoc_history.html:54
#: ops/templates/ops/adhoc_history.html:54
#: ops/templates/ops/task_history.html:60
#: ops/templates/ops/task_history.html:60
msgid "Ratio"
msgid "Ratio"
...
@@ -818,13 +842,13 @@ msgstr "比例"
...
@@ -818,13 +842,13 @@ msgstr "比例"
#: assets/templates/assets/admin_user_list.html:30
#: assets/templates/assets/admin_user_list.html:30
#: assets/templates/assets/asset_list.html:91
#: assets/templates/assets/asset_list.html:91
#: assets/templates/assets/domain_gateway_list.html:62
#: assets/templates/assets/domain_gateway_list.html:62
#: assets/templates/assets/domain_list.html:
18
#: assets/templates/assets/domain_list.html:
26
#: assets/templates/assets/label_list.html:17
#: assets/templates/assets/label_list.html:17
#: assets/templates/assets/system_user_list.html:3
4
#: assets/templates/assets/system_user_list.html:3
5
#: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:64
#: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:64
#: ops/templates/ops/task_history.html:65 ops/templates/ops/task_list.html:42
#: ops/templates/ops/task_history.html:65 ops/templates/ops/task_list.html:42
#: perms/templates/perms/asset_permission_list.html:60
#: perms/templates/perms/asset_permission_list.html:60
#: terminal/templates/terminal/session_list.html:8
0
#: terminal/templates/terminal/session_list.html:8
1
#: terminal/templates/terminal/terminal_list.html:36
#: terminal/templates/terminal/terminal_list.html:36
#: users/templates/users/user_group_list.html:15
#: users/templates/users/user_group_list.html:15
#: users/templates/users/user_list.html:29
#: users/templates/users/user_list.html:29
...
@@ -882,8 +906,8 @@ msgid "Refresh"
...
@@ -882,8 +906,8 @@ msgid "Refresh"
msgstr "刷新"
msgstr "刷新"
#: assets/templates/assets/asset_detail.html:300
#: assets/templates/assets/asset_detail.html:300
#: users/templates/users/user_detail.html:2
86
#: users/templates/users/user_detail.html:2
94
#: users/templates/users/user_detail.html:3
13
#: users/templates/users/user_detail.html:3
21
msgid "Update successfully!"
msgid "Update successfully!"
msgstr "更新成功"
msgstr "更新成功"
...
@@ -978,9 +1002,10 @@ msgid "Have assets, cancel"
...
@@ -978,9 +1002,10 @@ msgid "Have assets, cancel"
msgstr "存在资产,不能删除"
msgstr "存在资产,不能删除"
#: assets/templates/assets/asset_list.html:633
#: assets/templates/assets/asset_list.html:633
#: assets/templates/assets/system_user_list.html:133
#: assets/templates/assets/system_user_list.html:134
#: users/templates/users/user_detail.html:361
#: users/templates/users/user_detail.html:369
#: users/templates/users/user_detail.html:386
#: users/templates/users/user_detail.html:394
#: users/templates/users/user_detail.html:453
#: users/templates/users/user_group_list.html:81
#: users/templates/users/user_group_list.html:81
#: users/templates/users/user_list.html:195
#: users/templates/users/user_list.html:195
msgid "Are you sure?"
msgid "Are you sure?"
...
@@ -1003,7 +1028,7 @@ msgstr "删除"
...
@@ -1003,7 +1028,7 @@ msgstr "删除"
msgid "Asset Deleting failed."
msgid "Asset Deleting failed."
msgstr "删除失败"
msgstr "删除失败"
#: assets/templates/assets/asset_update.html:
59
#: assets/templates/assets/asset_update.html:
60
msgid "Configuration"
msgid "Configuration"
msgstr "配置"
msgstr "配置"
...
@@ -1020,7 +1045,7 @@ msgstr "您确定删除吗?"
...
@@ -1020,7 +1045,7 @@ msgstr "您确定删除吗?"
#: assets/templates/assets/domain_detail.html:21
#: assets/templates/assets/domain_detail.html:21
#: assets/templates/assets/domain_detail.html:64
#: assets/templates/assets/domain_detail.html:64
#: assets/templates/assets/domain_gateway_list.html:21
#: assets/templates/assets/domain_gateway_list.html:21
#: assets/templates/assets/domain_list.html:
16
#: assets/templates/assets/domain_list.html:
24
msgid "Gateway"
msgid "Gateway"
msgstr "网关"
msgstr "网关"
...
@@ -1040,7 +1065,7 @@ msgstr "创建网关"
...
@@ -1040,7 +1065,7 @@ msgstr "创建网关"
msgid "Test connection"
msgid "Test connection"
msgstr "测试连接"
msgstr "测试连接"
#: assets/templates/assets/domain_list.html:
6
assets/views/domain.py:46
#: assets/templates/assets/domain_list.html:
14
assets/views/domain.py:46
msgid "Create domain"
msgid "Create domain"
msgstr "创建网域"
msgstr "创建网域"
...
@@ -1053,17 +1078,17 @@ msgid "Assets of "
...
@@ -1053,17 +1078,17 @@ msgid "Assets of "
msgstr "资产"
msgstr "资产"
#: assets/templates/assets/system_user_asset.html:70
#: assets/templates/assets/system_user_asset.html:70
#: assets/templates/assets/system_user_detail.html:13
5
#: assets/templates/assets/system_user_detail.html:13
9
msgid "Push system user now"
msgid "Push system user now"
msgstr "立刻推送系统"
msgstr "立刻推送系统"
#: assets/templates/assets/system_user_asset.html:73
#: assets/templates/assets/system_user_asset.html:73
#: assets/templates/assets/system_user_detail.html:1
38
#: assets/templates/assets/system_user_detail.html:1
42
msgid "Push"
msgid "Push"
msgstr "推送"
msgstr "推送"
#: assets/templates/assets/system_user_asset.html:78
#: assets/templates/assets/system_user_asset.html:78
#: assets/templates/assets/system_user_detail.html:14
4
#: assets/templates/assets/system_user_detail.html:14
8
msgid "Test assets connective"
msgid "Test assets connective"
msgstr "测试资产可连接性"
msgstr "测试资产可连接性"
...
@@ -1075,28 +1100,23 @@ msgstr "任务已下发,查看ops任务列表"
...
@@ -1075,28 +1100,23 @@ msgstr "任务已下发,查看ops任务列表"
msgid "Task has been send, seen left assets status"
msgid "Task has been send, seen left assets status"
msgstr "任务已下发,查看左侧资产状态"
msgstr "任务已下发,查看左侧资产状态"
#: assets/templates/assets/system_user_detail.html:8
1
#: assets/templates/assets/system_user_detail.html:8
5
msgid "Home"
msgid "Home"
msgstr "家目录"
msgstr "家目录"
#: assets/templates/assets/system_user_detail.html:
87
#: assets/templates/assets/system_user_detail.html:
91
msgid "Uid"
msgid "Uid"
msgstr "Uid"
msgstr "Uid"
#: assets/templates/assets/system_user_detail.html:153
#: assets/templates/assets/system_user_detail.html:186
#: assets/templates/assets/system_user_detail.html:339
msgid "Clear auth"
msgstr "清除认证信息"
#: assets/templates/assets/system_user_detail.html:156
msgid "Clear"
msgstr "清除"
#: assets/templates/assets/system_user_detail.html:183
msgid "Add to node"
msgid "Add to node"
msgstr "添加到节点"
msgstr "添加到节点"
#: assets/templates/assets/system_user_detail.html:339
#: assets/templates/assets/system_user_detail.html:353
msgid "Clear auth"
msgstr "清除认证信息"
#: assets/templates/assets/system_user_detail.html:353
msgid "success"
msgid "success"
msgstr "成功"
msgstr "成功"
...
@@ -1105,20 +1125,20 @@ msgstr "成功"
...
@@ -1105,20 +1125,20 @@ msgstr "成功"
msgid "Create system user"
msgid "Create system user"
msgstr "创建系统用户"
msgstr "创建系统用户"
#: assets/templates/assets/system_user_list.html:13
4
#: assets/templates/assets/system_user_list.html:13
5
msgid "This will delete the selected System Users !!!"
msgid "This will delete the selected System Users !!!"
msgstr "删除选择系统用户"
msgstr "删除选择系统用户"
#: assets/templates/assets/system_user_list.html:14
2
#: assets/templates/assets/system_user_list.html:14
3
msgid "System Users Deleted."
msgid "System Users Deleted."
msgstr "已被删除"
msgstr "已被删除"
#: assets/templates/assets/system_user_list.html:14
3
#: assets/templates/assets/system_user_list.html:14
4
#: assets/templates/assets/system_user_list.html:14
8
#: assets/templates/assets/system_user_list.html:14
9
msgid "System Users Delete"
msgid "System Users Delete"
msgstr "删除系统用户"
msgstr "删除系统用户"
#: assets/templates/assets/system_user_list.html:14
7
#: assets/templates/assets/system_user_list.html:14
8
msgid "System Users Deleting failed."
msgid "System Users Deleting failed."
msgstr "系统用户删除失败"
msgstr "系统用户删除失败"
...
@@ -1166,7 +1186,7 @@ msgstr "网域详情"
...
@@ -1166,7 +1186,7 @@ msgstr "网域详情"
msgid "Domain gateway list"
msgid "Domain gateway list"
msgstr "域网关列表"
msgstr "域网关列表"
#: assets/views/domain.py:1
51
#: assets/views/domain.py:1
46
msgid "Update gateway"
msgid "Update gateway"
msgstr "创建网关"
msgstr "创建网关"
...
@@ -1214,7 +1234,8 @@ msgid "Filename"
...
@@ -1214,7 +1234,8 @@ msgid "Filename"
msgstr "文件名"
msgstr "文件名"
#: audits/models.py:15 audits/templates/audits/ftp_log_list.html:77
#: audits/models.py:15 audits/templates/audits/ftp_log_list.html:77
#: ops/templates/ops/task_list.html:39
#: ops/templates/ops/task_list.html:39 users/models/authentication.py:66
#: users/templates/users/user_detail.html:443
msgid "Success"
msgid "Success"
msgstr "成功"
msgstr "成功"
...
@@ -1223,7 +1244,7 @@ msgstr "成功"
...
@@ -1223,7 +1244,7 @@ msgstr "成功"
#: ops/templates/ops/adhoc_history_detail.html:61
#: ops/templates/ops/adhoc_history_detail.html:61
#: ops/templates/ops/task_history.html:58 perms/models.py:36
#: ops/templates/ops/task_history.html:58 perms/models.py:36
#: perms/templates/perms/asset_permission_detail.html:86 terminal/models.py:137
#: perms/templates/perms/asset_permission_detail.html:86 terminal/models.py:137
#: terminal/templates/terminal/session_list.html:7
7
#: terminal/templates/terminal/session_list.html:7
8
msgid "Date start"
msgid "Date start"
msgstr "开始日期"
msgstr "开始日期"
...
@@ -1410,45 +1431,60 @@ msgid ""
...
@@ -1410,45 +1431,60 @@ msgid ""
"for all users, including administrators)"
"for all users, including administrators)"
msgstr "开启后,用户登录必须使用MFA二次认证(对所有用户有效,包括管理员)"
msgstr "开启后,用户登录必须使用MFA二次认证(对所有用户有效,包括管理员)"
#: common/forms.py:184
#: common/forms.py:185
msgid "Limit the number of login failures"
msgstr "限制登录失败次数"
#: common/forms.py:190
msgid "No logon interval"
msgstr "禁止登录时间间隔"
#: common/forms.py:192
msgid ""
"Tip :(unit/minute) if the user has failed to log in for a limited number of "
"times, no login is allowed during this time interval."
msgstr ""
"提示:(单位 / 分钟)当用户登录失败次数达到限制后,那么在此时间间隔内禁止登录."
#: common/forms.py:198
msgid "Password minimum length"
msgid "Password minimum length"
msgstr "密码最小长度 "
msgstr "密码最小长度 "
#: common/forms.py:
191
#: common/forms.py:
205
msgid "Must contain capital letters"
msgid "Must contain capital letters"
msgstr "必须包含大写字母"
msgstr "必须包含大写字母"
#: common/forms.py:
193
#: common/forms.py:
207
msgid ""
msgid ""
"After opening, the user password changes and resets must contain uppercase "
"After opening, the user password changes and resets must contain uppercase "
"letters"
"letters"
msgstr "开启后,用户密码修改、重置必须包含大写字母"
msgstr "开启后,用户密码修改、重置必须包含大写字母"
#: common/forms.py:
199
#: common/forms.py:
213
msgid "Must contain lowercase letters"
msgid "Must contain lowercase letters"
msgstr "必须包含小写字母"
msgstr "必须包含小写字母"
#: common/forms.py:2
00
#: common/forms.py:2
14
msgid ""
msgid ""
"After opening, the user password changes and resets must contain lowercase "
"After opening, the user password changes and resets must contain lowercase "
"letters"
"letters"
msgstr "开启后,用户密码修改、重置必须包含小写字母"
msgstr "开启后,用户密码修改、重置必须包含小写字母"
#: common/forms.py:2
06
#: common/forms.py:2
20
msgid "Must contain numeric characters"
msgid "Must contain numeric characters"
msgstr "必须包含数字字符"
msgstr "必须包含数字字符"
#: common/forms.py:2
07
#: common/forms.py:2
21
msgid ""
msgid ""
"After opening, the user password changes and resets must contain numeric "
"After opening, the user password changes and resets must contain numeric "
"characters"
"characters"
msgstr "开启后,用户密码修改、重置必须包含数字字符"
msgstr "开启后,用户密码修改、重置必须包含数字字符"
#: common/forms.py:2
13
#: common/forms.py:2
27
msgid "Must contain special characters"
msgid "Must contain special characters"
msgstr "必须包含特殊字符"
msgstr "必须包含特殊字符"
#: common/forms.py:2
14
#: common/forms.py:2
28
msgid ""
msgid ""
"After opening, the user password changes and resets must contain special "
"After opening, the user password changes and resets must contain special "
"characters"
"characters"
...
@@ -1462,7 +1498,8 @@ msgstr ""
...
@@ -1462,7 +1498,8 @@ msgstr ""
msgid "discard time"
msgid "discard time"
msgstr ""
msgstr ""
#: common/models.py:29 users/templates/users/user_detail.html:96
#: common/models.py:29 users/models/authentication.py:51
#: users/templates/users/user_detail.html:96
msgid "Enabled"
msgid "Enabled"
msgstr "启用"
msgstr "启用"
...
@@ -1508,8 +1545,8 @@ msgid "Security setting"
...
@@ -1508,8 +1545,8 @@ msgid "Security setting"
msgstr "安全设置"
msgstr "安全设置"
#: common/templates/common/security_setting.html:42
#: common/templates/common/security_setting.html:42
msgid "
MFA setting
"
msgid "
User login settings
"
msgstr "
MFA
设置"
msgstr "
用户登录
设置"
#: common/templates/common/security_setting.html:46
#: common/templates/common/security_setting.html:46
msgid "Password check rule"
msgid "Password check rule"
...
@@ -1780,7 +1817,7 @@ msgid "Versions"
...
@@ -1780,7 +1817,7 @@ msgid "Versions"
msgstr "版本"
msgstr "版本"
#: ops/templates/ops/task_list.html:40
#: ops/templates/ops/task_list.html:40
#: users/templates/users/login_log_list.html:5
4
#: users/templates/users/login_log_list.html:5
7
msgid "Date"
msgid "Date"
msgstr "日期"
msgstr "日期"
...
@@ -1805,8 +1842,8 @@ msgstr "任务列表"
...
@@ -1805,8 +1842,8 @@ msgstr "任务列表"
msgid "Task run history"
msgid "Task run history"
msgstr "执行历史"
msgstr "执行历史"
#: perms/forms.py:18 users/forms.py:23
8 users/forms.py:243 users/forms.py:255
#: perms/forms.py:18 users/forms.py:23
9 users/forms.py:244 users/forms.py:256
#: users/forms.py:28
5
#: users/forms.py:28
6
msgid "Select users"
msgid "Select users"
msgstr "选择用户"
msgstr "选择用户"
...
@@ -1815,7 +1852,7 @@ msgstr "选择用户"
...
@@ -1815,7 +1852,7 @@ msgstr "选择用户"
#: perms/templates/perms/asset_permission_list.html:136 templates/_nav.html:14
#: perms/templates/perms/asset_permission_list.html:136 templates/_nav.html:14
#: users/models/group.py:23 users/models/user.py:55
#: users/models/group.py:23 users/models/user.py:55
#: users/templates/users/_select_user_modal.html:16
#: users/templates/users/_select_user_modal.html:16
#: users/templates/users/user_detail.html:
192
#: users/templates/users/user_detail.html:
200
#: users/templates/users/user_list.html:26
#: users/templates/users/user_list.html:26
msgid "User group"
msgid "User group"
msgstr "用户组"
msgstr "用户组"
...
@@ -1868,7 +1905,7 @@ msgid "Add node to this permission"
...
@@ -1868,7 +1905,7 @@ msgid "Add node to this permission"
msgstr "添加节点"
msgstr "添加节点"
#: perms/templates/perms/asset_permission_asset.html:125
#: perms/templates/perms/asset_permission_asset.html:125
#: users/templates/users/user_detail.html:2
09
#: users/templates/users/user_detail.html:2
17
msgid "Join"
msgid "Join"
msgstr "加入"
msgstr "加入"
...
@@ -1958,14 +1995,14 @@ msgstr "商业支持"
...
@@ -1958,14 +1995,14 @@ msgstr "商业支持"
msgid "Docs"
msgid "Docs"
msgstr "文档"
msgstr "文档"
#: templates/_header_bar.html:37 templates/_nav_user.html:9 users/forms.py:12
1
#: templates/_header_bar.html:37 templates/_nav_user.html:9 users/forms.py:12
2
#: users/templates/users/_user.html:39
#: users/templates/users/_user.html:39
#: users/templates/users/first_login.html:39
#: users/templates/users/first_login.html:39
#: users/templates/users/user_password_update.html:39
#: users/templates/users/user_password_update.html:39
#: users/templates/users/user_profile.html:17
#: users/templates/users/user_profile.html:17
#: users/templates/users/user_profile_update.html:37
#: users/templates/users/user_profile_update.html:37
#: users/templates/users/user_profile_update.html:57
#: users/templates/users/user_profile_update.html:57
#: users/templates/users/user_pubkey_update.html:37 users/views/user.py:34
4
#: users/templates/users/user_pubkey_update.html:37 users/views/user.py:34
3
msgid "Profile"
msgid "Profile"
msgstr "个人信息"
msgstr "个人信息"
...
@@ -1982,7 +2019,7 @@ msgid "Logout"
...
@@ -1982,7 +2019,7 @@ msgid "Logout"
msgstr "注销登录"
msgstr "注销登录"
#: templates/_header_bar.html:49 users/templates/users/login.html:44
#: templates/_header_bar.html:49 users/templates/users/login.html:44
#: users/templates/users/login.html:6
4
#: users/templates/users/login.html:6
8
msgid "Login"
msgid "Login"
msgstr "登录"
msgstr "登录"
...
@@ -2022,13 +2059,13 @@ msgstr "关闭"
...
@@ -2022,13 +2059,13 @@ msgstr "关闭"
#: templates/_nav.html:10 users/views/group.py:28 users/views/group.py:44
#: templates/_nav.html:10 users/views/group.py:28 users/views/group.py:44
#: users/views/group.py:62 users/views/group.py:79 users/views/group.py:95
#: users/views/group.py:62 users/views/group.py:79 users/views/group.py:95
#: users/views/login.py:
277 users/views/login.py:335 users/views/user.py:66
#: users/views/login.py:
330 users/views/login.py:388 users/views/user.py:65
#: users/views/user.py:8
1 users/views/user.py:103 users/views/user.py:174
#: users/views/user.py:8
0 users/views/user.py:102 users/views/user.py:175
#: users/views/user.py:3
29 users/views/user.py:381 users/views/user.py:416
#: users/views/user.py:3
30 users/views/user.py:380 users/views/user.py:415
msgid "Users"
msgid "Users"
msgstr "用户管理"
msgstr "用户管理"
#: templates/_nav.html:13 users/views/user.py:6
7
#: templates/_nav.html:13 users/views/user.py:6
6
msgid "User list"
msgid "User list"
msgstr "用户列表"
msgstr "用户列表"
...
@@ -2138,14 +2175,14 @@ msgstr "线程数"
...
@@ -2138,14 +2175,14 @@ msgstr "线程数"
msgid "Boot Time"
msgid "Boot Time"
msgstr "运行时间"
msgstr "运行时间"
#: terminal/models.py:132 terminal/templates/terminal/session_list.html:10
2
#: terminal/models.py:132 terminal/templates/terminal/session_list.html:10
4
msgid "Replay"
msgid "Replay"
msgstr "回放"
msgstr "回放"
#: terminal/models.py:133 terminal/templates/terminal/command_list.html:55
#: terminal/models.py:133 terminal/templates/terminal/command_list.html:55
#: terminal/templates/terminal/command_list.html:71
#: terminal/templates/terminal/command_list.html:71
#: terminal/templates/terminal/session_detail.html:48
#: terminal/templates/terminal/session_detail.html:48
#: terminal/templates/terminal/session_list.html:7
6
#: terminal/templates/terminal/session_list.html:7
7
msgid "Command"
msgid "Command"
msgstr "命令"
msgstr "命令"
...
@@ -2196,24 +2233,28 @@ msgstr "监控"
...
@@ -2196,24 +2233,28 @@ msgstr "监控"
msgid "Terminate session"
msgid "Terminate session"
msgstr "终止会话"
msgstr "终止会话"
#: terminal/templates/terminal/session_list.html:79
#: terminal/templates/terminal/session_list.html:76
msgid "Login from"
msgstr "登录来源"
#: terminal/templates/terminal/session_list.html:80
msgid "Duration"
msgid "Duration"
msgstr "时长"
msgstr "时长"
#: terminal/templates/terminal/session_list.html:10
4
#: terminal/templates/terminal/session_list.html:10
6
msgid "Monitor"
msgid "Monitor"
msgstr "监控"
msgstr "监控"
#: terminal/templates/terminal/session_list.html:106
#: terminal/templates/terminal/session_list.html:108
#: terminal/templates/terminal/session_list.html:108
#: terminal/templates/terminal/session_list.html:110
msgid "Terminate"
msgid "Terminate"
msgstr "终断"
msgstr "终断"
#: terminal/templates/terminal/session_list.html:12
0
#: terminal/templates/terminal/session_list.html:12
2
msgid "Terminate selected"
msgid "Terminate selected"
msgstr "终断所选"
msgstr "终断所选"
#: terminal/templates/terminal/session_list.html:14
0
#: terminal/templates/terminal/session_list.html:14
2
msgid "Terminate task send, waiting ..."
msgid "Terminate task send, waiting ..."
msgstr "终断任务已发送,请等待"
msgstr "终断任务已发送,请等待"
...
@@ -2283,6 +2324,10 @@ msgid ""
...
@@ -2283,6 +2324,10 @@ msgid ""
"You should use your ssh client tools connect terminal: {} <br /> <br />{}"
"You should use your ssh client tools connect terminal: {} <br /> <br />{}"
msgstr "你可以使用ssh客户端工具连接终端"
msgstr "你可以使用ssh客户端工具连接终端"
#: users/api.py:221 users/templates/users/login.html:50
msgid "Log in frequently and try again later"
msgstr "登录频繁, 稍后重试"
#: users/authentication.py:56
#: users/authentication.py:56
msgid "Invalid signature header. No credentials provided."
msgid "Invalid signature header. No credentials provided."
msgstr ""
msgstr ""
...
@@ -2334,11 +2379,11 @@ msgstr ""
...
@@ -2334,11 +2379,11 @@ msgstr ""
msgid "Invalid token or cache refreshed."
msgid "Invalid token or cache refreshed."
msgstr ""
msgstr ""
#: users/forms.py:3
8
#: users/forms.py:3
9
msgid "MFA code"
msgid "MFA code"
msgstr "MFA 验证码"
msgstr "MFA 验证码"
#: users/forms.py:
49
users/models/user.py:59
#: users/forms.py:
50
users/models/user.py:59
#: users/templates/users/_select_user_modal.html:15
#: users/templates/users/_select_user_modal.html:15
#: users/templates/users/user_detail.html:87
#: users/templates/users/user_detail.html:87
#: users/templates/users/user_list.html:25
#: users/templates/users/user_list.html:25
...
@@ -2346,31 +2391,31 @@ msgstr "MFA 验证码"
...
@@ -2346,31 +2391,31 @@ msgstr "MFA 验证码"
msgid "Role"
msgid "Role"
msgstr "角色"
msgstr "角色"
#: users/forms.py:5
2 users/forms.py:201
#: users/forms.py:5
3 users/forms.py:202
msgid "ssh public key"
msgid "ssh public key"
msgstr "ssh公钥"
msgstr "ssh公钥"
#: users/forms.py:5
3 users/forms.py:202
#: users/forms.py:5
4 users/forms.py:203
msgid "ssh-rsa AAAA..."
msgid "ssh-rsa AAAA..."
msgstr ""
msgstr ""
#: users/forms.py:5
4
#: users/forms.py:5
5
msgid "Paste user id_rsa.pub here."
msgid "Paste user id_rsa.pub here."
msgstr "复制用户公钥到这里"
msgstr "复制用户公钥到这里"
#: users/forms.py:7
2 users/templates/users/user_detail.html:200
#: users/forms.py:7
3 users/templates/users/user_detail.html:208
msgid "Join user groups"
msgid "Join user groups"
msgstr "添加到用户组"
msgstr "添加到用户组"
#: users/forms.py:8
3 users/forms.py:216
#: users/forms.py:8
4 users/forms.py:217
msgid "Public key should not be the same as your old one."
msgid "Public key should not be the same as your old one."
msgstr "不能和原来的密钥相同"
msgstr "不能和原来的密钥相同"
#: users/forms.py:8
7 users/forms.py:220
users/serializers.py:48
#: users/forms.py:8
8 users/forms.py:221
users/serializers.py:48
msgid "Not a valid ssh public key"
msgid "Not a valid ssh public key"
msgstr "ssh密钥不合法"
msgstr "ssh密钥不合法"
#: users/forms.py:12
7
#: users/forms.py:12
8
msgid ""
msgid ""
"Tip: when enabled, you will enter the MFA binding process the next time you "
"Tip: when enabled, you will enter the MFA binding process the next time you "
"log in. you can also directly bind in \"personal information -> quick "
"log in. you can also directly bind in \"personal information -> quick "
...
@@ -2379,16 +2424,17 @@ msgstr ""
...
@@ -2379,16 +2424,17 @@ msgstr ""
"提示:启用之后您将会在下次登录时进入MFA绑定流程;您也可以在(个人信息->快速修"
"提示:启用之后您将会在下次登录时进入MFA绑定流程;您也可以在(个人信息->快速修"
"改->更改MFA设置)中直接绑定!"
"改->更改MFA设置)中直接绑定!"
#: users/forms.py:13
7
#: users/forms.py:13
8
msgid "* Enable MFA authentication to make the account more secure."
msgid "* Enable MFA authentication to make the account more secure."
msgstr "* 启用MFA认证,使账号更加安全."
msgstr "* 启用MFA认证,使账号更加安全."
#: users/forms.py:14
2
users/models/user.py:71
#: users/forms.py:14
3 users/models/authentication.py:75
users/models/user.py:71
#: users/templates/users/first_login.html:45
#: users/templates/users/first_login.html:45
#: users/templates/users/login_log_list.html:54
msgid "MFA"
msgid "MFA"
msgstr "MFA"
msgstr "MFA"
#: users/forms.py:14
7
#: users/forms.py:14
8
msgid ""
msgid ""
"In order to protect you and your company, please keep your account, password "
"In order to protect you and your company, please keep your account, password "
"and key sensitive information properly. (for example: setting complex "
"and key sensitive information properly. (for example: setting complex "
...
@@ -2397,41 +2443,41 @@ msgstr ""
...
@@ -2397,41 +2443,41 @@ msgstr ""
"为了保护您和公司的安全,请妥善保管您的账户、密码和密钥等重要敏感信息;(如:"
"为了保护您和公司的安全,请妥善保管您的账户、密码和密钥等重要敏感信息;(如:"
"设置复杂密码,启用MFA认证)"
"设置复杂密码,启用MFA认证)"
#: users/forms.py:15
4
users/templates/users/first_login.html:48
#: users/forms.py:15
5
users/templates/users/first_login.html:48
#: users/templates/users/first_login.html:107
#: users/templates/users/first_login.html:107
#: users/templates/users/first_login.html:130
#: users/templates/users/first_login.html:130
msgid "Finish"
msgid "Finish"
msgstr "完成"
msgstr "完成"
#: users/forms.py:16
0
#: users/forms.py:16
1
msgid "Old password"
msgid "Old password"
msgstr "原来密码"
msgstr "原来密码"
#: users/forms.py:16
5
#: users/forms.py:16
6
msgid "New password"
msgid "New password"
msgstr "新密码"
msgstr "新密码"
#: users/forms.py:17
0
#: users/forms.py:17
1
msgid "Confirm password"
msgid "Confirm password"
msgstr "确认密码"
msgstr "确认密码"
#: users/forms.py:18
0
#: users/forms.py:18
1
msgid "Old password error"
msgid "Old password error"
msgstr "原来密码错误"
msgstr "原来密码错误"
#: users/forms.py:18
8
#: users/forms.py:18
9
msgid "Password does not match"
msgid "Password does not match"
msgstr "密码不一致"
msgstr "密码不一致"
#: users/forms.py:
199
#: users/forms.py:
200
msgid "Automatically configure and download the SSH key"
msgid "Automatically configure and download the SSH key"
msgstr "自动配置并下载SSH密钥"
msgstr "自动配置并下载SSH密钥"
#: users/forms.py:20
3
#: users/forms.py:20
4
msgid "Paste your id_rsa.pub here."
msgid "Paste your id_rsa.pub here."
msgstr "复制你的公钥到这里"
msgstr "复制你的公钥到这里"
#: users/forms.py:23
1
users/models/user.py:79
#: users/forms.py:23
2
users/models/user.py:79
#: users/templates/users/first_login.html:42
#: users/templates/users/first_login.html:42
#: users/templates/users/user_password_update.html:45
#: users/templates/users/user_password_update.html:45
#: users/templates/users/user_profile.html:68
#: users/templates/users/user_profile.html:68
...
@@ -2444,27 +2490,57 @@ msgstr "ssh公钥"
...
@@ -2444,27 +2490,57 @@ msgstr "ssh公钥"
msgid "Private Token"
msgid "Private Token"
msgstr "ssh密钥"
msgstr "ssh密钥"
#: users/models/authentication.py:46
#: users/models/authentication.py:50 users/templates/users/user_detail.html:98
msgid "Disabled"
msgstr "禁用"
#: users/models/authentication.py:52 users/models/authentication.py:60
msgid "-"
msgstr ""
#: users/models/authentication.py:61
msgid "Username/password check failed"
msgstr "用户名/密码 校验失败"
#: users/models/authentication.py:62
msgid "MFA authentication failed"
msgstr "MFA 认证失败"
#: users/models/authentication.py:67
msgid "Failed"
msgstr "失败"
#: users/models/authentication.py:71
msgid "Login type"
msgid "Login type"
msgstr "登录方式"
msgstr "登录方式"
#: users/models/authentication.py:
47
#: users/models/authentication.py:
72
msgid "Login ip"
msgid "Login ip"
msgstr "登录IP"
msgstr "登录IP"
#: users/models/authentication.py:
48
#: users/models/authentication.py:
73
msgid "Login city"
msgid "Login city"
msgstr "登录城市"
msgstr "登录城市"
#: users/models/authentication.py:
49
#: users/models/authentication.py:
74
msgid "User agent"
msgid "User agent"
msgstr "Agent"
msgstr "Agent"
#: users/models/authentication.py:50
#: users/models/authentication.py:76
#: users/templates/users/login_log_list.html:55
msgid "Reason"
msgstr "原因"
#: users/models/authentication.py:77
#: users/templates/users/login_log_list.html:56
msgid "Status"
msgstr "状态"
#: users/models/authentication.py:78
msgid "Date login"
msgid "Date login"
msgstr "登录日期"
msgstr "登录日期"
#: users/models/user.py:30 users/models/user.py:3
39
#: users/models/user.py:30 users/models/user.py:3
41
msgid "Administrator"
msgid "Administrator"
msgstr "管理员"
msgstr "管理员"
...
@@ -2506,7 +2582,7 @@ msgstr "微信"
...
@@ -2506,7 +2582,7 @@ msgstr "微信"
msgid "Source"
msgid "Source"
msgstr "用户来源"
msgstr "用户来源"
#: users/models/user.py:34
2
#: users/models/user.py:34
4
msgid "Administrator is the super user of system"
msgid "Administrator is the super user of system"
msgstr "Administrator是初始的超级管理员"
msgstr "Administrator是初始的超级管理员"
...
@@ -2586,7 +2662,7 @@ msgid " for more information"
...
@@ -2586,7 +2662,7 @@ msgid " for more information"
msgstr "获取更多信息"
msgstr "获取更多信息"
#: users/templates/users/forgot_password.html:26
#: users/templates/users/forgot_password.html:26
#: users/templates/users/login.html:7
3
#: users/templates/users/login.html:7
7
msgid "Forgot password"
msgid "Forgot password"
msgstr "忘记密码"
msgstr "忘记密码"
...
@@ -2594,7 +2670,7 @@ msgstr "忘记密码"
...
@@ -2594,7 +2670,7 @@ msgstr "忘记密码"
msgid "Input your email, that will send a mail to your"
msgid "Input your email, that will send a mail to your"
msgstr "输入您的邮箱, 将会发一封重置邮件到您的邮箱中"
msgstr "输入您的邮箱, 将会发一封重置邮件到您的邮箱中"
#: users/templates/users/login.html:5
0
#: users/templates/users/login.html:5
3
msgid "Captcha invalid"
msgid "Captcha invalid"
msgstr "验证码错误"
msgstr "验证码错误"
...
@@ -2623,7 +2699,7 @@ msgid "Can't provide security? Please contact the administrator!"
...
@@ -2623,7 +2699,7 @@ msgid "Can't provide security? Please contact the administrator!"
msgstr "如果不能提供MFA验证码,请联系管理员!"
msgstr "如果不能提供MFA验证码,请联系管理员!"
#: users/templates/users/reset_password.html:46
#: users/templates/users/reset_password.html:46
#: users/templates/users/user_detail.html:3
52
users/utils.py:80
#: users/templates/users/user_detail.html:3
60
users/utils.py:80
msgid "Reset password"
msgid "Reset password"
msgstr "重置密码"
msgstr "重置密码"
...
@@ -2649,7 +2725,7 @@ msgid "Setting"
...
@@ -2649,7 +2725,7 @@ msgid "Setting"
msgstr "设置"
msgstr "设置"
#: users/templates/users/user_create.html:4
#: users/templates/users/user_create.html:4
#: users/templates/users/user_list.html:16 users/views/user.py:8
1
#: users/templates/users/user_list.html:16 users/views/user.py:8
0
msgid "Create user"
msgid "Create user"
msgstr "创建用户"
msgstr "创建用户"
...
@@ -2658,7 +2734,7 @@ msgid "Reset link will be generated and sent to the user. "
...
@@ -2658,7 +2734,7 @@ msgid "Reset link will be generated and sent to the user. "
msgstr "生成重置密码连接,通过邮件发送给用户"
msgstr "生成重置密码连接,通过邮件发送给用户"
#: users/templates/users/user_detail.html:19
#: users/templates/users/user_detail.html:19
#: users/templates/users/user_granted_asset.html:18 users/views/user.py:17
5
#: users/templates/users/user_granted_asset.html:18 users/views/user.py:17
6
msgid "User detail"
msgid "User detail"
msgstr "用户详情"
msgstr "用户详情"
...
@@ -2673,10 +2749,6 @@ msgstr "授权的资产"
...
@@ -2673,10 +2749,6 @@ msgstr "授权的资产"
msgid "Force enabled"
msgid "Force enabled"
msgstr "强制启用"
msgstr "强制启用"
#: users/templates/users/user_detail.html:98
msgid "Disabled"
msgstr "禁用"
#: users/templates/users/user_detail.html:119
#: users/templates/users/user_detail.html:119
#: users/templates/users/user_profile.html:108
#: users/templates/users/user_profile.html:108
msgid "Last login"
msgid "Last login"
...
@@ -2699,44 +2771,57 @@ msgstr "发送"
...
@@ -2699,44 +2771,57 @@ msgstr "发送"
msgid "Send reset ssh key mail"
msgid "Send reset ssh key mail"
msgstr "发送重置密钥邮件"
msgstr "发送重置密钥邮件"
#: users/templates/users/user_detail.html:295
#: users/templates/users/user_detail.html:186
#: users/templates/users/user_detail.html:444
msgid "Unblock user"
msgstr "解除登录限制"
#: users/templates/users/user_detail.html:189
msgid "Unblock"
msgstr "解除"
#: users/templates/users/user_detail.html:303
msgid "Goto profile page enable MFA"
msgid "Goto profile page enable MFA"
msgstr "请去个人信息页面启用自己的MFA"
msgstr "请去个人信息页面启用自己的MFA"
#: users/templates/users/user_detail.html:35
1
#: users/templates/users/user_detail.html:35
9
msgid "An e-mail has been sent to the user`s mailbox."
msgid "An e-mail has been sent to the user`s mailbox."
msgstr "已发送邮件到用户邮箱"
msgstr "已发送邮件到用户邮箱"
#: users/templates/users/user_detail.html:3
62
#: users/templates/users/user_detail.html:3
70
msgid "This will reset the user password and send a reset mail"
msgid "This will reset the user password and send a reset mail"
msgstr "将失效用户当前密码,并发送重设密码邮件到用户邮箱"
msgstr "将失效用户当前密码,并发送重设密码邮件到用户邮箱"
#: users/templates/users/user_detail.html:3
76
#: users/templates/users/user_detail.html:3
84
msgid ""
msgid ""
"The reset-ssh-public-key E-mail has been sent successfully. Please inform "
"The reset-ssh-public-key E-mail has been sent successfully. Please inform "
"the user to update his new ssh public key."
"the user to update his new ssh public key."
msgstr "重设密钥邮件将会发送到用户邮箱"
msgstr "重设密钥邮件将会发送到用户邮箱"
#: users/templates/users/user_detail.html:3
77
#: users/templates/users/user_detail.html:3
85
msgid "Reset SSH public key"
msgid "Reset SSH public key"
msgstr "重置SSH密钥"
msgstr "重置SSH密钥"
#: users/templates/users/user_detail.html:3
87
#: users/templates/users/user_detail.html:3
95
msgid "This will reset the user public key and send a reset mail"
msgid "This will reset the user public key and send a reset mail"
msgstr "将会失效用户当前密钥,并发送重置邮件到用户邮箱"
msgstr "将会失效用户当前密钥,并发送重置邮件到用户邮箱"
#: users/templates/users/user_detail.html:4
04
#: users/templates/users/user_detail.html:4
12
#: users/templates/users/user_profile.html:211
#: users/templates/users/user_profile.html:211
msgid "Successfully updated the SSH public key."
msgid "Successfully updated the SSH public key."
msgstr "更新ssh密钥成功"
msgstr "更新ssh密钥成功"
#: users/templates/users/user_detail.html:4
05
#: users/templates/users/user_detail.html:4
13
#: users/templates/users/user_detail.html:4
09
#: users/templates/users/user_detail.html:4
17
#: users/templates/users/user_profile.html:212
#: users/templates/users/user_profile.html:212
#: users/templates/users/user_profile.html:217
#: users/templates/users/user_profile.html:217
msgid "User SSH public key update"
msgid "User SSH public key update"
msgstr "ssh密钥"
msgstr "ssh密钥"
#: users/templates/users/user_detail.html:454
msgid "After unlocking the user, the user can log in normally."
msgstr "解除用户登录限制后,此用户即可正常登录"
#: users/templates/users/user_group_create_update.html:31
#: users/templates/users/user_group_create_update.html:31
msgid "Cancel"
msgid "Cancel"
msgstr "取消"
msgstr "取消"
...
@@ -2793,8 +2878,8 @@ msgstr "用户删除失败"
...
@@ -2793,8 +2878,8 @@ msgstr "用户删除失败"
msgid "Administrator Settings force MFA login"
msgid "Administrator Settings force MFA login"
msgstr "管理员设置强制使用MFA登录"
msgstr "管理员设置强制使用MFA登录"
#: users/templates/users/user_profile.html:116 users/views/user.py:20
4
#: users/templates/users/user_profile.html:116 users/views/user.py:20
5
#: users/views/user.py:25
8
#: users/views/user.py:25
9
msgid "User groups"
msgid "User groups"
msgstr "用户组"
msgstr "用户组"
...
@@ -2840,7 +2925,7 @@ msgid ""
...
@@ -2840,7 +2925,7 @@ msgid ""
"corresponding private key."
"corresponding private key."
msgstr "新的公钥已设置成功,请下载对应的私钥"
msgstr "新的公钥已设置成功,请下载对应的私钥"
#: users/templates/users/user_update.html:4 users/views/user.py:10
4
#: users/templates/users/user_update.html:4 users/views/user.py:10
3
msgid "Update user"
msgid "Update user"
msgstr "更新用户"
msgstr "更新用户"
...
@@ -2849,7 +2934,7 @@ msgid "Create account successfully"
...
@@ -2849,7 +2934,7 @@ msgid "Create account successfully"
msgstr "创建账户成功"
msgstr "创建账户成功"
#: users/utils.py:43
#: users/utils.py:43
#,
fuzzy,
python-format
#, python-format
msgid ""
msgid ""
"\n"
"\n"
" Hello %(name)s:\n"
" Hello %(name)s:\n"
...
@@ -2978,7 +3063,7 @@ msgstr "禁用或失效"
...
@@ -2978,7 +3063,7 @@ msgstr "禁用或失效"
msgid "Password or SSH public key invalid"
msgid "Password or SSH public key invalid"
msgstr "密码或密钥不合法"
msgstr "密码或密钥不合法"
#: users/utils.py:2
90 users/utils.py:300
#: users/utils.py:2
89 users/utils.py:299
msgid "Bit"
msgid "Bit"
msgstr " 位"
msgstr " 位"
...
@@ -2994,103 +3079,112 @@ msgstr "更新用户组"
...
@@ -2994,103 +3079,112 @@ msgstr "更新用户组"
msgid "User group granted asset"
msgid "User group granted asset"
msgstr "用户组授权资产"
msgstr "用户组授权资产"
#: users/views/login.py:
62
#: users/views/login.py:
75
msgid "Please enable cookies and try again."
msgid "Please enable cookies and try again."
msgstr "设置你的浏览器支持cookie"
msgstr "设置你的浏览器支持cookie"
#: users/views/login.py:1
28 users/views/user.py:501 users/views/user.py:526
#: users/views/login.py:1
78 users/views/user.py:500 users/views/user.py:525
msgid "MFA code invalid"
msgid "MFA code invalid"
msgstr "MFA码认证失败"
msgstr "MFA码认证失败"
#: users/views/login.py:
154
#: users/views/login.py:
207
msgid "Logout success"
msgid "Logout success"
msgstr "退出登录成功"
msgstr "退出登录成功"
#: users/views/login.py:
155
#: users/views/login.py:
208
msgid "Logout success, return login page"
msgid "Logout success, return login page"
msgstr "退出登录成功,返回到登录页面"
msgstr "退出登录成功,返回到登录页面"
#: users/views/login.py:
171
#: users/views/login.py:
224
msgid "Email address invalid, please input again"
msgid "Email address invalid, please input again"
msgstr "邮箱地址错误,重新输入"
msgstr "邮箱地址错误,重新输入"
#: users/views/login.py:
184
#: users/views/login.py:
237
msgid "Send reset password message"
msgid "Send reset password message"
msgstr "发送重置密码邮件"
msgstr "发送重置密码邮件"
#: users/views/login.py:
185
#: users/views/login.py:
238
msgid "Send reset password mail success, login your mail box and follow it "
msgid "Send reset password mail success, login your mail box and follow it "
msgstr ""
msgstr ""
"发送重置邮件成功, 请登录邮箱查看, 按照提示操作 (如果没收到,请等待3-5分钟)"
"发送重置邮件成功, 请登录邮箱查看, 按照提示操作 (如果没收到,请等待3-5分钟)"
#: users/views/login.py:
198
#: users/views/login.py:
251
msgid "Reset password success"
msgid "Reset password success"
msgstr "重置密码成功"
msgstr "重置密码成功"
#: users/views/login.py:
199
#: users/views/login.py:
252
msgid "Reset password success, return to login page"
msgid "Reset password success, return to login page"
msgstr "重置密码成功,返回到登录页面"
msgstr "重置密码成功,返回到登录页面"
#: users/views/login.py:2
20 users/views/login.py:233
#: users/views/login.py:2
73 users/views/login.py:286
msgid "Token invalid or expired"
msgid "Token invalid or expired"
msgstr "Token错误或失效"
msgstr "Token错误或失效"
#: users/views/login.py:2
29
#: users/views/login.py:2
82
msgid "Password not same"
msgid "Password not same"
msgstr "密码不一致"
msgstr "密码不一致"
#: users/views/login.py:2
39 users/views/user.py:116 users/views/user.py:399
#: users/views/login.py:2
92 users/views/user.py:118 users/views/user.py:398
msgid "* Your password does not meet the requirements"
msgid "* Your password does not meet the requirements"
msgstr "* 您的密码不符合要求"
msgstr "* 您的密码不符合要求"
#: users/views/login.py:
277
#: users/views/login.py:
330
msgid "First login"
msgid "First login"
msgstr "首次登陆"
msgstr "首次登陆"
#: users/views/login.py:3
36
#: users/views/login.py:3
89
msgid "Login log list"
msgid "Login log list"
msgstr "登录日志"
msgstr "登录日志"
#: users/views/user.py:12
8
#: users/views/user.py:12
9
msgid "Bulk update user success"
msgid "Bulk update user success"
msgstr "批量更新用户成功"
msgstr "批量更新用户成功"
#: users/views/user.py:23
3
#: users/views/user.py:23
4
msgid "Invalid file."
msgid "Invalid file."
msgstr "文件不合法"
msgstr "文件不合法"
#: users/views/user.py:33
0
#: users/views/user.py:33
1
msgid "User granted assets"
msgid "User granted assets"
msgstr "用户授权资产"
msgstr "用户授权资产"
#: users/views/user.py:36
3
#: users/views/user.py:36
2
msgid "Profile setting"
msgid "Profile setting"
msgstr "个人信息设置"
msgstr "个人信息设置"
#: users/views/user.py:38
2
#: users/views/user.py:38
1
msgid "Password update"
msgid "Password update"
msgstr "密码更新"
msgstr "密码更新"
#: users/views/user.py:41
7
#: users/views/user.py:41
6
msgid "Public key update"
msgid "Public key update"
msgstr "密钥更新"
msgstr "密钥更新"
#: users/views/user.py:45
8
#: users/views/user.py:45
7
msgid "Password invalid"
msgid "Password invalid"
msgstr "用户名或密码无效"
msgstr "用户名或密码无效"
#: users/views/user.py:55
2
#: users/views/user.py:55
1
msgid "MFA enable success"
msgid "MFA enable success"
msgstr "MFA 绑定成功"
msgstr "MFA 绑定成功"
#: users/views/user.py:55
3
#: users/views/user.py:55
2
msgid "MFA enable success, return login page"
msgid "MFA enable success, return login page"
msgstr "MFA 绑定成功,返回到登录页面"
msgstr "MFA 绑定成功,返回到登录页面"
#: users/views/user.py:55
5
#: users/views/user.py:55
4
msgid "MFA disable success"
msgid "MFA disable success"
msgstr "MFA 解绑成功"
msgstr "MFA 解绑成功"
#: users/views/user.py:55
6
#: users/views/user.py:55
5
msgid "MFA disable success, return login page"
msgid "MFA disable success, return login page"
msgstr "MFA 解绑成功,返回登录页面"
msgstr "MFA 解绑成功,返回登录页面"
#~ msgid "Unblock user successfully. "
#~ msgstr "解除登录限制成功"
#~ msgid "Clear"
#~ msgstr "清除"
#~ msgid "MFA setting"
#~ msgstr "MFA 设置"
apps/jumpserver/settings.py
View file @
722bf786
...
@@ -343,10 +343,11 @@ if AUTH_LDAP:
...
@@ -343,10 +343,11 @@ if AUTH_LDAP:
AUTHENTICATION_BACKENDS
.
insert
(
0
,
AUTH_LDAP_BACKEND
)
AUTHENTICATION_BACKENDS
.
insert
(
0
,
AUTH_LDAP_BACKEND
)
# Celery using redis as broker
# Celery using redis as broker
CELERY_BROKER_URL
=
'redis://:
%(password)
s@
%(host)
s:
%(port)
s/
3
'
%
{
CELERY_BROKER_URL
=
'redis://:
%(password)
s@
%(host)
s:
%(port)
s/
%(db)
s
'
%
{
'password'
:
CONFIG
.
REDIS_PASSWORD
if
CONFIG
.
REDIS_PASSWORD
else
''
,
'password'
:
CONFIG
.
REDIS_PASSWORD
if
CONFIG
.
REDIS_PASSWORD
else
''
,
'host'
:
CONFIG
.
REDIS_HOST
or
'127.0.0.1'
,
'host'
:
CONFIG
.
REDIS_HOST
or
'127.0.0.1'
,
'port'
:
CONFIG
.
REDIS_PORT
or
6379
,
'port'
:
CONFIG
.
REDIS_PORT
or
6379
,
'db'
:
CONFIG
.
REDIS_DB_CELERY_BROKER
or
3
,
}
}
CELERY_TASK_SERIALIZER
=
'pickle'
CELERY_TASK_SERIALIZER
=
'pickle'
CELERY_RESULT_SERIALIZER
=
'pickle'
CELERY_RESULT_SERIALIZER
=
'pickle'
...
@@ -367,10 +368,11 @@ CELERY_WORKER_HIJACK_ROOT_LOGGER = False
...
@@ -367,10 +368,11 @@ CELERY_WORKER_HIJACK_ROOT_LOGGER = False
CACHES
=
{
CACHES
=
{
'default'
:
{
'default'
:
{
'BACKEND'
:
'redis_cache.RedisCache'
,
'BACKEND'
:
'redis_cache.RedisCache'
,
'LOCATION'
:
'redis://:
%(password)
s@
%(host)
s:
%(port)
s/
4
'
%
{
'LOCATION'
:
'redis://:
%(password)
s@
%(host)
s:
%(port)
s/
%(db)
s
'
%
{
'password'
:
CONFIG
.
REDIS_PASSWORD
if
CONFIG
.
REDIS_PASSWORD
else
''
,
'password'
:
CONFIG
.
REDIS_PASSWORD
if
CONFIG
.
REDIS_PASSWORD
else
''
,
'host'
:
CONFIG
.
REDIS_HOST
or
'127.0.0.1'
,
'host'
:
CONFIG
.
REDIS_HOST
or
'127.0.0.1'
,
'port'
:
CONFIG
.
REDIS_PORT
or
6379
,
'port'
:
CONFIG
.
REDIS_PORT
or
6379
,
'db'
:
CONFIG
.
REDIS_DB_CACHE
or
4
,
}
}
}
}
}
}
...
@@ -403,6 +405,8 @@ TERMINAL_REPLAY_STORAGE = {
...
@@ -403,6 +405,8 @@ TERMINAL_REPLAY_STORAGE = {
DEFAULT_PASSWORD_MIN_LENGTH
=
6
DEFAULT_PASSWORD_MIN_LENGTH
=
6
DEFAULT_LOGIN_LIMIT_COUNT
=
3
DEFAULT_LOGIN_LIMIT_TIME
=
30
# Django bootstrap3 setting, more see http://django-bootstrap3.readthedocs.io/en/latest/settings.html
# Django bootstrap3 setting, more see http://django-bootstrap3.readthedocs.io/en/latest/settings.html
BOOTSTRAP3
=
{
BOOTSTRAP3
=
{
...
...
apps/ops/inventory.py
View file @
722bf786
...
@@ -93,7 +93,7 @@ class JMSInventory(BaseInventory):
...
@@ -93,7 +93,7 @@ class JMSInventory(BaseInventory):
if
gateway
.
password
:
if
gateway
.
password
:
proxy_command_list
.
insert
(
proxy_command_list
.
insert
(
0
,
"sshpass -p
{}
"
.
format
(
gateway
.
password
)
0
,
"sshpass -p
'{}'
"
.
format
(
gateway
.
password
)
)
)
if
gateway
.
private_key
:
if
gateway
.
private_key
:
proxy_command_list
.
append
(
"-i {}"
.
format
(
gateway
.
private_key_file
))
proxy_command_list
.
append
(
"-i {}"
.
format
(
gateway
.
private_key_file
))
...
...
apps/perms/api.py
View file @
722bf786
...
@@ -77,9 +77,9 @@ class UserGrantedAssetsApi(ListAPIView):
...
@@ -77,9 +77,9 @@ class UserGrantedAssetsApi(ListAPIView):
util
=
AssetPermissionUtil
(
user
)
util
=
AssetPermissionUtil
(
user
)
for
k
,
v
in
util
.
get_assets
()
.
items
():
for
k
,
v
in
util
.
get_assets
()
.
items
():
if
k
.
is_unixlike
():
if
k
.
is_unixlike
():
system_users_granted
=
[
s
for
s
in
v
if
s
.
protocol
==
'ssh'
]
system_users_granted
=
[
s
for
s
in
v
if
s
.
protocol
in
[
'ssh'
,
'telnet'
]
]
else
:
else
:
system_users_granted
=
[
s
for
s
in
v
if
s
.
protocol
==
'rdp'
]
system_users_granted
=
[
s
for
s
in
v
if
s
.
protocol
in
[
'rdp'
,
'telnet'
]
]
k
.
system_users_granted
=
system_users_granted
k
.
system_users_granted
=
system_users_granted
queryset
.
append
(
k
)
queryset
.
append
(
k
)
return
queryset
return
queryset
...
@@ -128,9 +128,9 @@ class UserGrantedNodesWithAssetsApi(ListAPIView):
...
@@ -128,9 +128,9 @@ class UserGrantedNodesWithAssetsApi(ListAPIView):
assets
=
_assets
.
keys
()
assets
=
_assets
.
keys
()
for
k
,
v
in
_assets
.
items
():
for
k
,
v
in
_assets
.
items
():
if
k
.
is_unixlike
():
if
k
.
is_unixlike
():
system_users_granted
=
[
s
for
s
in
v
if
s
.
protocol
==
'ssh'
]
system_users_granted
=
[
s
for
s
in
v
if
s
.
protocol
in
[
'ssh'
,
'telnet'
]
]
else
:
else
:
system_users_granted
=
[
s
for
s
in
v
if
s
.
protocol
==
'rdp'
]
system_users_granted
=
[
s
for
s
in
v
if
s
.
protocol
in
[
'rdp'
,
'telnet'
]
]
k
.
system_users_granted
=
system_users_granted
k
.
system_users_granted
=
system_users_granted
node
.
assets_granted
=
assets
node
.
assets_granted
=
assets
queryset
.
append
(
node
)
queryset
.
append
(
node
)
...
...
apps/perms/urls/views_urls.py
View file @
722bf786
...
@@ -6,13 +6,11 @@ from .. import views
...
@@ -6,13 +6,11 @@ from .. import views
app_name
=
'perms'
app_name
=
'perms'
urlpatterns
=
[
urlpatterns
=
[
url
(
r'^asset-permission$'
,
views
.
AssetPermissionListView
.
as_view
(),
name
=
'asset-permission-list'
),
url
(
r'^asset-permission
/
$'
,
views
.
AssetPermissionListView
.
as_view
(),
name
=
'asset-permission-list'
),
url
(
r'^asset-permission/create$'
,
views
.
AssetPermissionCreateView
.
as_view
(),
name
=
'asset-permission-create'
),
url
(
r'^asset-permission/create
/
$'
,
views
.
AssetPermissionCreateView
.
as_view
(),
name
=
'asset-permission-create'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/update$'
,
views
.
AssetPermissionUpdateView
.
as_view
(),
name
=
'asset-permission-update'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/update
/
$'
,
views
.
AssetPermissionUpdateView
.
as_view
(),
name
=
'asset-permission-update'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})$'
,
views
.
AssetPermissionDetailView
.
as_view
(),
name
=
'asset-permission-detail'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})
/
$'
,
views
.
AssetPermissionDetailView
.
as_view
(),
name
=
'asset-permission-detail'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/delete$'
,
views
.
AssetPermissionDeleteView
.
as_view
(),
name
=
'asset-permission-delete'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/delete
/
$'
,
views
.
AssetPermissionDeleteView
.
as_view
(),
name
=
'asset-permission-delete'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/user$'
,
views
.
AssetPermissionUserView
.
as_view
(),
name
=
'asset-permission-user-list'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/user
/
$'
,
views
.
AssetPermissionUserView
.
as_view
(),
name
=
'asset-permission-user-list'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/asset$'
,
views
.
AssetPermissionAssetView
.
as_view
(),
name
=
'asset-permission-asset-list'
),
url
(
r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/asset
/
$'
,
views
.
AssetPermissionAssetView
.
as_view
(),
name
=
'asset-permission-asset-list'
),
]
]
apps/static/js/jumpserver.js
View file @
722bf786
...
@@ -173,14 +173,14 @@ function APIUpdateAttr(props) {
...
@@ -173,14 +173,14 @@ function APIUpdateAttr(props) {
}
}
if
(
typeof
props
.
success
===
'function'
)
{
if
(
typeof
props
.
success
===
'function'
)
{
return
props
.
success
(
data
);
return
props
.
success
(
data
);
}
}
}).
fail
(
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
}).
fail
(
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
if
(
flash_message
)
{
if
(
flash_message
)
{
toastr
.
error
(
fail_message
);
toastr
.
error
(
fail_message
);
}
}
if
(
typeof
props
.
error
===
'function'
)
{
if
(
typeof
props
.
error
===
'function'
)
{
return
props
.
error
(
jqXHR
.
responseText
);
return
props
.
error
(
jqXHR
.
responseText
);
}
}
});
});
// return true;
// return true;
}
}
...
@@ -198,7 +198,8 @@ function objectDelete(obj, name, url, redirectTo) {
...
@@ -198,7 +198,8 @@ function objectDelete(obj, name, url, redirectTo) {
}
}
};
};
var
fail
=
function
()
{
var
fail
=
function
()
{
swal
(
"错误"
,
"删除"
+
"[ "
+
name
+
" ]"
+
"遇到错误"
,
"error"
);
// swal("错误", "删除"+"[ "+name+" ]"+"遇到错误", "error");
swal
(
"错误"
,
"[ "
+
name
+
" ]"
+
"正在被资产使用中,请先解除资产绑定"
,
"error"
);
};
};
APIUpdateAttr
({
APIUpdateAttr
({
url
:
url
,
url
:
url
,
...
@@ -219,7 +220,7 @@ function objectDelete(obj, name, url, redirectTo) {
...
@@ -219,7 +220,7 @@ function objectDelete(obj, name, url, redirectTo) {
confirmButtonText
:
'确认'
,
confirmButtonText
:
'确认'
,
closeOnConfirm
:
true
,
closeOnConfirm
:
true
,
},
function
()
{
},
function
()
{
doDelete
()
doDelete
()
});
});
}
}
...
@@ -272,7 +273,7 @@ jumpserver.initDataTable = function (options) {
...
@@ -272,7 +273,7 @@ jumpserver.initDataTable = function (options) {
$
(
td
).
html
(
'<input type="checkbox" class="text-center ipt_check" id=99991937>'
.
replace
(
'99991937'
,
cellData
));
$
(
td
).
html
(
'<input type="checkbox" class="text-center ipt_check" id=99991937>'
.
replace
(
'99991937'
,
cellData
));
}
}
},
},
{
className
:
'text-center'
,
targets
:
'_all'
}
{
className
:
'text-center'
,
render
:
$
.
fn
.
dataTable
.
render
.
text
(),
targets
:
'_all'
}
];
];
columnDefs
=
options
.
columnDefs
?
options
.
columnDefs
.
concat
(
columnDefs
)
:
columnDefs
;
columnDefs
=
options
.
columnDefs
?
options
.
columnDefs
.
concat
(
columnDefs
)
:
columnDefs
;
var
select
=
{
var
select
=
{
...
...
apps/templates/_footer.html
View file @
722bf786
<div
class=
"footer fixed"
>
<div
class=
"footer fixed"
>
<div
class=
"pull-right"
>
<div
class=
"pull-right"
>
Version
<strong>
1.3.
2
-{% include '_build.html' %}
</strong>
GPLv2.
Version
<strong>
1.3.
3
-{% include '_build.html' %}
</strong>
GPLv2.
<!--<img style="display: none" src="http://www.jumpserver.org/img/evaluate_avatar1.jpg">-->
<!--<img style="display: none" src="http://www.jumpserver.org/img/evaluate_avatar1.jpg">-->
</div>
</div>
<div>
<div>
...
...
apps/terminal/api.py
View file @
722bf786
...
@@ -259,10 +259,35 @@ class SessionReplayViewSet(viewsets.ViewSet):
...
@@ -259,10 +259,35 @@ class SessionReplayViewSet(viewsets.ViewSet):
serializer_class
=
ReplaySerializer
serializer_class
=
ReplaySerializer
permission_classes
=
(
IsSuperUserOrAppUser
,)
permission_classes
=
(
IsSuperUserOrAppUser
,)
session
=
None
session
=
None
upload_to
=
'replay'
# 仅添加到本地存储中
def
gen_session_path
(
self
):
def
get_session_path
(
self
,
version
=
2
):
"""
获取session日志的文件路径
:param version: 原来后缀是 .gz,为了统一新版本改为 .replay.gz
:return:
"""
suffix
=
'.replay.gz'
if
version
==
1
:
suffix
=
'.gz'
date
=
self
.
session
.
date_start
.
strftime
(
'
%
Y-
%
m-
%
d'
)
date
=
self
.
session
.
date_start
.
strftime
(
'
%
Y-
%
m-
%
d'
)
return
os
.
path
.
join
(
date
,
str
(
self
.
session
.
id
)
+
'.gz'
)
return
os
.
path
.
join
(
date
,
str
(
self
.
session
.
id
)
+
suffix
)
def
get_local_path
(
self
,
version
=
2
):
session_path
=
self
.
get_session_path
(
version
=
version
)
if
version
==
2
:
local_path
=
os
.
path
.
join
(
self
.
upload_to
,
session_path
)
else
:
local_path
=
session_path
return
local_path
def
save_to_storage
(
self
,
f
):
local_path
=
self
.
get_local_path
()
try
:
name
=
default_storage
.
save
(
local_path
,
f
)
return
name
,
None
except
OSError
as
e
:
return
None
,
e
def
create
(
self
,
request
,
*
args
,
**
kwargs
):
def
create
(
self
,
request
,
*
args
,
**
kwargs
):
session_id
=
kwargs
.
get
(
'pk'
)
session_id
=
kwargs
.
get
(
'pk'
)
...
@@ -271,46 +296,49 @@ class SessionReplayViewSet(viewsets.ViewSet):
...
@@ -271,46 +296,49 @@ class SessionReplayViewSet(viewsets.ViewSet):
if
serializer
.
is_valid
():
if
serializer
.
is_valid
():
file
=
serializer
.
validated_data
[
'file'
]
file
=
serializer
.
validated_data
[
'file'
]
file_path
=
self
.
gen_session_path
(
)
name
,
err
=
self
.
save_to_storage
(
file
)
try
:
if
not
name
:
default_storage
.
save
(
file_path
,
file
)
msg
=
"Failed save replay `{}`: {}"
.
format
(
session_id
,
err
)
return
Response
({
'url'
:
default_storage
.
url
(
file_path
)},
logger
.
error
(
msg
)
status
=
201
)
return
Response
({
'msg'
:
str
(
err
)},
status
=
400
)
except
IOError
:
url
=
default_storage
.
url
(
name
)
return
Response
(
"Save error"
,
status
=
500
)
return
Response
({
'url'
:
url
},
status
=
201
)
else
:
else
:
logger
.
error
(
msg
=
'Upload data invalid: {}'
.
format
(
serializer
.
errors
)
'Update load data invalid: {}'
.
format
(
serializer
.
errors
)
)
logger
.
error
(
msg
)
return
Response
({
'msg'
:
serializer
.
errors
},
status
=
401
)
return
Response
({
'msg'
:
serializer
.
errors
},
status
=
401
)
def
retrieve
(
self
,
request
,
*
args
,
**
kwargs
):
def
retrieve
(
self
,
request
,
*
args
,
**
kwargs
):
session_id
=
kwargs
.
get
(
'pk'
)
session_id
=
kwargs
.
get
(
'pk'
)
self
.
session
=
get_object_or_404
(
Session
,
id
=
session_id
)
self
.
session
=
get_object_or_404
(
Session
,
id
=
session_id
)
path
=
self
.
gen_session_path
()
if
default_storage
.
exists
(
path
):
# 新版本和老版本的文件后缀不同
url
=
default_storage
.
url
(
path
)
session_path
=
self
.
get_session_path
()
# 存在外部存储上的路径
return
redirect
(
url
)
local_path
=
self
.
get_local_path
()
else
:
local_path_v1
=
self
.
get_local_path
(
version
=
1
)
config
=
settings
.
TERMINAL_REPLAY_STORAGE
configs
=
copy
.
deepcopy
(
config
)
# 去default storage中查找
for
cfg
in
config
:
for
_local_path
in
(
local_path
,
local_path_v1
,
session_path
):
if
config
[
cfg
][
'TYPE'
]
==
'server'
:
if
default_storage
.
exists
(
_local_path
):
configs
.
__delitem__
(
cfg
)
url
=
default_storage
.
url
(
_local_path
)
return
redirect
(
url
)
if
not
configs
:
return
HttpResponseNotFound
()
# 去定义的外部storage查找
configs
=
settings
.
TERMINAL_REPLAY_STORAGE
date
=
self
.
session
.
date_start
.
strftime
(
'
%
Y-
%
m-
%
d'
)
configs
=
{
k
:
v
for
k
,
v
in
configs
.
items
()
if
v
[
'TYPE'
]
!=
'server'
}
file_path
=
os
.
path
.
join
(
date
,
str
(
self
.
session
.
id
)
+
'.replay.gz'
)
if
not
configs
:
target_path
=
default_storage
.
base_location
+
'/'
+
path
return
HttpResponseNotFound
()
storage
=
jms_storage
.
get_multi_object_storage
(
configs
)
ok
,
err
=
storage
.
download
(
file_path
,
target_path
)
target_path
=
os
.
path
.
join
(
default_storage
.
base_location
,
local_path
)
# 保存到storage的路径
if
ok
:
target_dir
=
os
.
path
.
dirname
(
target_path
)
return
redirect
(
default_storage
.
url
(
path
))
if
not
os
.
path
.
isdir
(
target_dir
):
else
:
os
.
makedirs
(
target_dir
,
exist_ok
=
True
)
logger
.
error
(
"Failed download replay file: {}"
.
format
(
err
))
storage
=
jms_storage
.
get_multi_object_storage
(
configs
)
return
HttpResponseNotFound
()
ok
,
err
=
storage
.
download
(
session_path
,
target_path
)
if
not
ok
:
logger
.
error
(
"Failed download replay file: {}"
.
format
(
err
))
return
HttpResponseNotFound
()
return
redirect
(
default_storage
.
url
(
local_path
))
class
SessionReplayV2ViewSet
(
SessionReplayViewSet
):
class
SessionReplayV2ViewSet
(
SessionReplayViewSet
):
...
...
apps/terminal/templates/terminal/session_list.html
View file @
722bf786
...
@@ -73,6 +73,7 @@
...
@@ -73,6 +73,7 @@
<th
class=
"text-center"
>
{% trans 'System user' %}
</th>
<th
class=
"text-center"
>
{% trans 'System user' %}
</th>
<th
class=
"text-center"
>
{% trans 'Remote addr' %}
</th>
<th
class=
"text-center"
>
{% trans 'Remote addr' %}
</th>
<th
class=
"text-center"
>
{% trans 'Protocol' %}
</th>
<th
class=
"text-center"
>
{% trans 'Protocol' %}
</th>
<th
class=
"text-center"
>
{% trans 'Login from' %}
</th>
<th
class=
"text-center"
>
{% trans 'Command' %}
</th>
<th
class=
"text-center"
>
{% trans 'Command' %}
</th>
<th
class=
"text-center"
>
{% trans 'Date start' %}
</th>
<th
class=
"text-center"
>
{% trans 'Date start' %}
</th>
{#
<th
class=
"text-center"
>
{% trans 'Date last active' %}
</th>
#}
{#
<th
class=
"text-center"
>
{% trans 'Date last active' %}
</th>
#}
...
@@ -92,6 +93,7 @@
...
@@ -92,6 +93,7 @@
<td
class=
"text-center"
>
{{ session.system_user }}
</td>
<td
class=
"text-center"
>
{{ session.system_user }}
</td>
<td
class=
"text-center"
>
{{ session.remote_addr|default:"" }}
</td>
<td
class=
"text-center"
>
{{ session.remote_addr|default:"" }}
</td>
<td
class=
"text-center"
>
{{ session.protocol }}
</td>
<td
class=
"text-center"
>
{{ session.protocol }}
</td>
<td
class=
"text-center"
>
{{ session.get_login_from_display }}
</td>
<td
class=
"text-center"
>
{{ session.id | get_session_command_amount }}
</td>
<td
class=
"text-center"
>
{{ session.id | get_session_command_amount }}
</td>
<td
class=
"text-center"
>
{{ session.date_start }}
</td>
<td
class=
"text-center"
>
{{ session.date_start }}
</td>
...
...
apps/users/api.py
View file @
722bf786
...
@@ -3,6 +3,7 @@ import uuid
...
@@ -3,6 +3,7 @@ import uuid
from
django.core.cache
import
cache
from
django.core.cache
import
cache
from
django.urls
import
reverse
from
django.urls
import
reverse
from
django.utils.translation
import
ugettext
as
_
from
rest_framework
import
generics
from
rest_framework
import
generics
from
rest_framework.permissions
import
AllowAny
,
IsAuthenticated
from
rest_framework.permissions
import
AllowAny
,
IsAuthenticated
...
@@ -14,10 +15,11 @@ from .serializers import UserSerializer, UserGroupSerializer, \
...
@@ -14,10 +15,11 @@ from .serializers import UserSerializer, UserGroupSerializer, \
UserGroupUpdateMemeberSerializer
,
UserPKUpdateSerializer
,
\
UserGroupUpdateMemeberSerializer
,
UserPKUpdateSerializer
,
\
UserUpdateGroupSerializer
,
ChangeUserPasswordSerializer
UserUpdateGroupSerializer
,
ChangeUserPasswordSerializer
from
.tasks
import
write_login_log_async
from
.tasks
import
write_login_log_async
from
.models
import
User
,
UserGroup
from
.models
import
User
,
UserGroup
,
LoginLog
from
.permissions
import
IsSuperUser
,
IsValidUser
,
IsCurrentUserOrReadOnly
,
\
from
.permissions
import
IsSuperUser
,
IsValidUser
,
IsCurrentUserOrReadOnly
,
\
IsSuperUserOrAppUser
IsSuperUserOrAppUser
from
.utils
import
check_user_valid
,
generate_token
,
get_login_ip
,
check_otp_code
from
.utils
import
check_user_valid
,
generate_token
,
get_login_ip
,
\
check_otp_code
,
set_user_login_failed_count_to_cache
,
is_block_login
from
common.mixins
import
IDInFilterMixin
from
common.mixins
import
IDInFilterMixin
from
common.utils
import
get_logger
from
common.utils
import
get_logger
...
@@ -93,6 +95,22 @@ class UserUpdatePKApi(generics.UpdateAPIView):
...
@@ -93,6 +95,22 @@ class UserUpdatePKApi(generics.UpdateAPIView):
user
.
save
()
user
.
save
()
class
UserUnblockPKApi
(
generics
.
UpdateAPIView
):
queryset
=
User
.
objects
.
all
()
permission_classes
=
(
IsSuperUser
,)
serializer_class
=
UserSerializer
key_prefix_limit
=
"_LOGIN_LIMIT_{}_{}"
key_prefix_block
=
"_LOGIN_BLOCK_{}"
def
perform_update
(
self
,
serializer
):
user
=
self
.
get_object
()
username
=
user
.
username
if
user
else
''
key_limit
=
self
.
key_prefix_limit
.
format
(
username
,
'*'
)
key_block
=
self
.
key_prefix_block
.
format
(
username
)
cache
.
delete_pattern
(
key_limit
)
cache
.
delete
(
key_block
)
class
UserGroupViewSet
(
IDInFilterMixin
,
BulkModelViewSet
):
class
UserGroupViewSet
(
IDInFilterMixin
,
BulkModelViewSet
):
queryset
=
UserGroup
.
objects
.
all
()
queryset
=
UserGroup
.
objects
.
all
()
serializer_class
=
UserGroupSerializer
serializer_class
=
UserGroupSerializer
...
@@ -128,16 +146,12 @@ class UserToken(APIView):
...
@@ -128,16 +146,12 @@ class UserToken(APIView):
return
Response
({
'error'
:
msg
},
status
=
406
)
return
Response
({
'error'
:
msg
},
status
=
406
)
class
UserProfile
(
APIView
):
class
UserProfile
(
generics
.
Retrieve
APIView
):
permission_classes
=
(
Is
ValidUser
,)
permission_classes
=
(
Is
Authenticated
,)
serializer_class
=
UserSerializer
serializer_class
=
UserSerializer
def
get
(
self
,
request
):
def
get_object
(
self
):
# return Response(request.user.to_json())
return
self
.
request
.
user
return
Response
(
self
.
serializer_class
(
request
.
user
)
.
data
)
def
post
(
self
,
request
):
return
Response
(
self
.
serializer_class
(
request
.
user
)
.
data
)
class
UserOtpAuthApi
(
APIView
):
class
UserOtpAuthApi
(
APIView
):
...
@@ -153,10 +167,23 @@ class UserOtpAuthApi(APIView):
...
@@ -153,10 +167,23 @@ class UserOtpAuthApi(APIView):
return
Response
({
'msg'
:
'请先进行用户名和密码验证'
},
status
=
401
)
return
Response
({
'msg'
:
'请先进行用户名和密码验证'
},
status
=
401
)
if
not
check_otp_code
(
user
.
otp_secret_key
,
otp_code
):
if
not
check_otp_code
(
user
.
otp_secret_key
,
otp_code
):
data
=
{
'username'
:
user
.
username
,
'mfa'
:
int
(
user
.
otp_enabled
),
'reason'
:
LoginLog
.
REASON_MFA
,
'status'
:
False
}
self
.
write_login_log
(
request
,
data
)
return
Response
({
'msg'
:
'MFA认证失败'
},
status
=
401
)
return
Response
({
'msg'
:
'MFA认证失败'
},
status
=
401
)
data
=
{
'username'
:
user
.
username
,
'mfa'
:
int
(
user
.
otp_enabled
),
'reason'
:
LoginLog
.
REASON_NOTHING
,
'status'
:
True
}
self
.
write_login_log
(
request
,
data
)
token
=
generate_token
(
request
,
user
)
token
=
generate_token
(
request
,
user
)
self
.
write_login_log
(
request
,
user
)
return
Response
(
return
Response
(
{
{
'token'
:
token
,
'token'
:
token
,
...
@@ -165,7 +192,7 @@ class UserOtpAuthApi(APIView):
...
@@ -165,7 +192,7 @@ class UserOtpAuthApi(APIView):
)
)
@staticmethod
@staticmethod
def
write_login_log
(
request
,
user
):
def
write_login_log
(
request
,
data
):
login_ip
=
request
.
data
.
get
(
'remote_addr'
,
None
)
login_ip
=
request
.
data
.
get
(
'remote_addr'
,
None
)
login_type
=
request
.
data
.
get
(
'login_type'
,
''
)
login_type
=
request
.
data
.
get
(
'login_type'
,
''
)
user_agent
=
request
.
data
.
get
(
'HTTP_USER_AGENT'
,
''
)
user_agent
=
request
.
data
.
get
(
'HTTP_USER_AGENT'
,
''
)
...
@@ -173,25 +200,54 @@ class UserOtpAuthApi(APIView):
...
@@ -173,25 +200,54 @@ class UserOtpAuthApi(APIView):
if
not
login_ip
:
if
not
login_ip
:
login_ip
=
get_login_ip
(
request
)
login_ip
=
get_login_ip
(
request
)
write_login_log_async
.
delay
(
tmp_data
=
{
user
.
username
,
ip
=
login_ip
,
'ip'
:
login_ip
,
type
=
login_type
,
user_agent
=
user_agent
,
'type'
:
login_type
,
)
'user_agent'
:
user_agent
}
data
.
update
(
tmp_data
)
write_login_log_async
.
delay
(
**
data
)
class
UserAuthApi
(
APIView
):
class
UserAuthApi
(
APIView
):
permission_classes
=
(
AllowAny
,)
permission_classes
=
(
AllowAny
,)
serializer_class
=
UserSerializer
serializer_class
=
UserSerializer
key_prefix_limit
=
"_LOGIN_LIMIT_{}_{}"
key_prefix_block
=
"_LOGIN_BLOCK_{}"
def
post
(
self
,
request
):
def
post
(
self
,
request
):
user
,
msg
=
self
.
check_user_valid
(
request
)
# limit login
username
=
request
.
data
.
get
(
'username'
)
ip
=
request
.
data
.
get
(
'remote_addr'
,
None
)
ip
=
ip
if
ip
else
get_login_ip
(
request
)
key_limit
=
self
.
key_prefix_limit
.
format
(
username
,
ip
)
key_block
=
self
.
key_prefix_block
.
format
(
username
)
if
is_block_login
(
key_limit
):
msg
=
_
(
"Log in frequently and try again later"
)
return
Response
({
'msg'
:
msg
},
status
=
401
)
user
,
msg
=
self
.
check_user_valid
(
request
)
if
not
user
:
if
not
user
:
data
=
{
'username'
:
request
.
data
.
get
(
'username'
,
''
),
'mfa'
:
LoginLog
.
MFA_UNKNOWN
,
'reason'
:
LoginLog
.
REASON_PASSWORD
,
'status'
:
False
}
self
.
write_login_log
(
request
,
data
)
set_user_login_failed_count_to_cache
(
key_limit
,
key_block
)
return
Response
({
'msg'
:
msg
},
status
=
401
)
return
Response
({
'msg'
:
msg
},
status
=
401
)
if
not
user
.
otp_enabled
:
if
not
user
.
otp_enabled
:
data
=
{
'username'
:
user
.
username
,
'mfa'
:
int
(
user
.
otp_enabled
),
'reason'
:
LoginLog
.
REASON_NOTHING
,
'status'
:
True
}
self
.
write_login_log
(
request
,
data
)
token
=
generate_token
(
request
,
user
)
token
=
generate_token
(
request
,
user
)
self
.
write_login_log
(
request
,
user
)
return
Response
(
return
Response
(
{
{
'token'
:
token
,
'token'
:
token
,
...
@@ -208,7 +264,8 @@ class UserAuthApi(APIView):
...
@@ -208,7 +264,8 @@ class UserAuthApi(APIView):
'otp_url'
:
reverse
(
'api-users:user-otp-auth'
),
'otp_url'
:
reverse
(
'api-users:user-otp-auth'
),
'seed'
:
seed
,
'seed'
:
seed
,
'user'
:
self
.
serializer_class
(
user
)
.
data
'user'
:
self
.
serializer_class
(
user
)
.
data
},
status
=
300
)
},
status
=
300
)
@staticmethod
@staticmethod
def
check_user_valid
(
request
):
def
check_user_valid
(
request
):
...
@@ -222,7 +279,7 @@ class UserAuthApi(APIView):
...
@@ -222,7 +279,7 @@ class UserAuthApi(APIView):
return
user
,
msg
return
user
,
msg
@staticmethod
@staticmethod
def
write_login_log
(
request
,
user
):
def
write_login_log
(
request
,
data
):
login_ip
=
request
.
data
.
get
(
'remote_addr'
,
None
)
login_ip
=
request
.
data
.
get
(
'remote_addr'
,
None
)
login_type
=
request
.
data
.
get
(
'login_type'
,
''
)
login_type
=
request
.
data
.
get
(
'login_type'
,
''
)
user_agent
=
request
.
data
.
get
(
'HTTP_USER_AGENT'
,
''
)
user_agent
=
request
.
data
.
get
(
'HTTP_USER_AGENT'
,
''
)
...
@@ -230,10 +287,14 @@ class UserAuthApi(APIView):
...
@@ -230,10 +287,14 @@ class UserAuthApi(APIView):
if
not
login_ip
:
if
not
login_ip
:
login_ip
=
get_login_ip
(
request
)
login_ip
=
get_login_ip
(
request
)
write_login_log_async
.
delay
(
tmp_data
=
{
user
.
username
,
ip
=
login_ip
,
'ip'
:
login_ip
,
type
=
login_type
,
user_agent
=
user_agent
,
'type'
:
login_type
,
)
'user_agent'
:
user_agent
,
}
data
.
update
(
tmp_data
)
write_login_log_async
.
delay
(
**
data
)
class
UserConnectionTokenApi
(
APIView
):
class
UserConnectionTokenApi
(
APIView
):
...
...
apps/users/models/authentication.py
View file @
722bf786
...
@@ -41,12 +41,40 @@ class LoginLog(models.Model):
...
@@ -41,12 +41,40 @@ class LoginLog(models.Model):
(
'W'
,
'Web'
),
(
'W'
,
'Web'
),
(
'T'
,
'Terminal'
),
(
'T'
,
'Terminal'
),
)
)
MFA_DISABLED
=
0
MFA_ENABLED
=
1
MFA_UNKNOWN
=
2
MFA_CHOICE
=
(
(
MFA_DISABLED
,
_
(
'Disabled'
)),
(
MFA_ENABLED
,
_
(
'Enabled'
)),
(
MFA_UNKNOWN
,
_
(
'-'
)),
)
REASON_NOTHING
=
0
REASON_PASSWORD
=
1
REASON_MFA
=
2
REASON_CHOICE
=
(
(
REASON_NOTHING
,
_
(
'-'
)),
(
REASON_PASSWORD
,
_
(
'Username/password check failed'
)),
(
REASON_MFA
,
_
(
'MFA authentication failed'
)),
)
STATUS_CHOICE
=
(
(
True
,
_
(
'Success'
)),
(
False
,
_
(
'Failed'
))
)
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
username
=
models
.
CharField
(
max_length
=
20
,
verbose_name
=
_
(
'Username'
))
username
=
models
.
CharField
(
max_length
=
20
,
verbose_name
=
_
(
'Username'
))
type
=
models
.
CharField
(
choices
=
LOGIN_TYPE_CHOICE
,
max_length
=
2
,
verbose_name
=
_
(
'Login type'
))
type
=
models
.
CharField
(
choices
=
LOGIN_TYPE_CHOICE
,
max_length
=
2
,
verbose_name
=
_
(
'Login type'
))
ip
=
models
.
GenericIPAddressField
(
verbose_name
=
_
(
'Login ip'
))
ip
=
models
.
GenericIPAddressField
(
verbose_name
=
_
(
'Login ip'
))
city
=
models
.
CharField
(
max_length
=
254
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Login city'
))
city
=
models
.
CharField
(
max_length
=
254
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Login city'
))
user_agent
=
models
.
CharField
(
max_length
=
254
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'User agent'
))
user_agent
=
models
.
CharField
(
max_length
=
254
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'User agent'
))
mfa
=
models
.
SmallIntegerField
(
default
=
MFA_UNKNOWN
,
choices
=
MFA_CHOICE
,
verbose_name
=
_
(
'MFA'
))
reason
=
models
.
SmallIntegerField
(
default
=
REASON_NOTHING
,
choices
=
REASON_CHOICE
,
verbose_name
=
_
(
'Reason'
))
status
=
models
.
BooleanField
(
max_length
=
2
,
default
=
True
,
choices
=
STATUS_CHOICE
,
verbose_name
=
_
(
'Status'
))
datetime
=
models
.
DateTimeField
(
auto_now_add
=
True
,
verbose_name
=
_
(
'Date login'
))
datetime
=
models
.
DateTimeField
(
auto_now_add
=
True
,
verbose_name
=
_
(
'Date login'
))
class
Meta
:
class
Meta
:
...
...
apps/users/templates/users/login.html
View file @
722bf786
...
@@ -45,13 +45,17 @@
...
@@ -45,13 +45,17 @@
</div>
</div>
<form
class=
"m-t"
role=
"form"
method=
"post"
action=
""
>
<form
class=
"m-t"
role=
"form"
method=
"post"
action=
""
>
{% csrf_token %}
{% csrf_token %}
{% if form.errors %}
{% if block_login %}
<p
class=
"red-fonts"
>
{% trans 'Log in frequently and try again later' %}
</p>
{% elif form.errors %}
{% if 'captcha' in form.errors %}
{% if 'captcha' in form.errors %}
<p
class=
"red-fonts"
>
{% trans 'Captcha invalid' %}
</p>
<p
class=
"red-fonts"
>
{% trans 'Captcha invalid' %}
</p>
{% else %}
{% else %}
<p
class=
"red-fonts"
>
{{ form.non_field_errors.as_text }}
</p>
<p
class=
"red-fonts"
>
{{ form.non_field_errors.as_text }}
</p>
{% endif %}
{% endif %}
{% endif %}
{% endif %}
<div
class=
"form-group"
>
<div
class=
"form-group"
>
<input
type=
"text"
class=
"form-control"
name=
"{{ form.username.html_name }}"
placeholder=
"{% trans 'Username' %}"
required=
""
value=
"{% if form.username.value %}{{ form.username.value }}{% endif %}"
>
<input
type=
"text"
class=
"form-control"
name=
"{{ form.username.html_name }}"
placeholder=
"{% trans 'Username' %}"
required=
""
value=
"{% if form.username.value %}{{ form.username.value }}{% endif %}"
>
</div>
</div>
...
...
apps/users/templates/users/login_log_list.html
View file @
722bf786
...
@@ -51,6 +51,9 @@
...
@@ -51,6 +51,9 @@
<th
class=
"text-center"
>
{% trans 'UA' %}
</th>
<th
class=
"text-center"
>
{% trans 'UA' %}
</th>
<th
class=
"text-center"
>
{% trans 'IP' %}
</th>
<th
class=
"text-center"
>
{% trans 'IP' %}
</th>
<th
class=
"text-center"
>
{% trans 'City' %}
</th>
<th
class=
"text-center"
>
{% trans 'City' %}
</th>
<th
class=
"text-center"
>
{% trans 'MFA' %}
</th>
<th
class=
"text-center"
>
{% trans 'Reason' %}
</th>
<th
class=
"text-center"
>
{% trans 'Status' %}
</th>
<th
class=
"text-center"
>
{% trans 'Date' %}
</th>
<th
class=
"text-center"
>
{% trans 'Date' %}
</th>
{% endblock %}
{% endblock %}
...
@@ -65,6 +68,9 @@
...
@@ -65,6 +68,9 @@
</td>
</td>
<td
class=
"text-center"
>
{{ login_log.ip }}
</td>
<td
class=
"text-center"
>
{{ login_log.ip }}
</td>
<td
class=
"text-center"
>
{{ login_log.city }}
</td>
<td
class=
"text-center"
>
{{ login_log.city }}
</td>
<td
class=
"text-center"
>
{{ login_log.get_mfa_display }}
</td>
<td
class=
"text-center"
>
{{ login_log.get_reason_display }}
</td>
<td
class=
"text-center"
>
{{ login_log.get_status_display }}
</td>
<td
class=
"text-center"
>
{{ login_log.datetime }}
</td>
<td
class=
"text-center"
>
{{ login_log.datetime }}
</td>
</tr>
</tr>
{% endfor %}
{% endfor %}
...
...
apps/users/templates/users/user_detail.html
View file @
722bf786
...
@@ -182,6 +182,14 @@
...
@@ -182,6 +182,14 @@
</span>
</span>
</td>
</td>
</tr>
</tr>
<tr
style=
"{% if not unblock %}display:none{% endif %}"
>
<td>
{% trans 'Unblock user' %}
</td>
<td>
<span
class=
"pull-right"
>
<button
type=
"button"
class=
"btn btn-primary btn-xs"
id=
"btn-unblock-user"
style=
"width: 54px"
>
{% trans 'Unblock' %}
</button>
</span>
</td>
</tr>
</tbody>
</tbody>
</table>
</table>
</div>
</div>
...
@@ -275,7 +283,7 @@ $(document).ready(function() {
...
@@ -275,7 +283,7 @@ $(document).ready(function() {
.
on
(
'select2:unselect'
,
function
(
evt
)
{
.
on
(
'select2:unselect'
,
function
(
evt
)
{
var
data
=
evt
.
params
.
data
;
var
data
=
evt
.
params
.
data
;
delete
jumpserver
.
nodes_selected
[
data
.
id
];
delete
jumpserver
.
nodes_selected
[
data
.
id
];
})
})
;
})
})
.
on
(
'click'
,
'#is_active'
,
function
()
{
.
on
(
'click'
,
'#is_active'
,
function
()
{
var
the_url
=
"{% url 'api-users:user-detail' pk=user_object.id %}"
;
var
the_url
=
"{% url 'api-users:user-detail' pk=user_object.id %}"
;
...
@@ -293,7 +301,7 @@ $(document).ready(function() {
...
@@ -293,7 +301,7 @@ $(document).ready(function() {
.
on
(
'click'
,
'#force_enable_otp'
,
function
()
{
.
on
(
'click'
,
'#force_enable_otp'
,
function
()
{
{
%
if
request
.
user
==
user_object
%
}
{
%
if
request
.
user
==
user_object
%
}
toastr
.
error
(
"{% trans 'Goto profile page enable MFA' %}"
);
toastr
.
error
(
"{% trans 'Goto profile page enable MFA' %}"
);
return
return
;
{
%
endif
%
}
{
%
endif
%
}
var
the_url
=
"{% url 'api-users:user-detail' pk=user_object.id %}"
;
var
the_url
=
"{% url 'api-users:user-detail' pk=user_object.id %}"
;
...
@@ -421,11 +429,45 @@ $(document).ready(function() {
...
@@ -421,11 +429,45 @@ $(document).ready(function() {
APIUpdateAttr({ url: the_url, body: JSON.stringify(body), success: success, error: fail});
APIUpdateAttr({ url: the_url, body: JSON.stringify(body), success: success, error: fail});
}).on('click', '.btn-delete-user', function () {
}).on('click', '.btn-delete-user', function () {
var $this = $(this);
var $this = $(this);
var name = "{{ user.name }}";
var name = "{{ user
_object
.name }}";
var uid = "{{ user.id }}";
var uid = "{{ user
_object
.id }}";
var the_url = '{% url "api-users:user-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', uid);
var the_url = '{% url "api-users:user-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', uid);
var redirect_url = "{% url 'users:user-list' %}";
var redirect_url = "{% url 'users:user-list' %}";
objectDelete($this, name, the_url, redirect_url);
objectDelete($this, name, the_url, redirect_url);
}).on('click', '#btn-unblock-user', function () {
function doReset() {
{#var the_url = '{% url "api-users:user-reset-password" pk=user_object.id %}';#}
var the_url = '{% url "api-users:user-unblock" pk=user_object.id %}';
var body = {};
var success = function() {
var msg = "{% trans "Success" %}";
{#swal("{% trans 'Unblock user' %}", msg, "success");#}
swal({
title: "{% trans 'Unblock user' %}",
text: msg,
type: "success"
}, function() {
location.reload()
}
);
};
APIUpdateAttr({
url: the_url,
body: JSON.stringify(body),
success: success
});
}
swal({
title: "{% trans 'Are you sure?' %}",
text: "{% trans "After unlocking the user, the user can log in normally."%}",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "{% trans 'Confirm' %}",
closeOnConfirm: false
}, function() {
doReset();
});
})
})
</script>
</script>
{% endblock %}
{% endblock %}
apps/users/templates/users/user_list.html
View file @
722bf786
...
@@ -59,7 +59,7 @@ function initTable() {
...
@@ -59,7 +59,7 @@ function initTable() {
ele
:
$
(
'#user_list_table'
),
ele
:
$
(
'#user_list_table'
),
columnDefs
:
[
columnDefs
:
[
{
targets
:
1
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
{
targets
:
1
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
detail_btn
=
'<a href="{% url "users:user-detail" pk=DEFAULT_PK %}">'
+
cellData
+
'</a>'
;
var
detail_btn
=
'<a href="{% url "users:user-detail" pk=DEFAULT_PK %}">'
+
escape
(
cellData
)
+
'</a>'
;
$
(
td
).
html
(
detail_btn
.
replace
(
"{{ DEFAULT_PK }}"
,
rowData
.
id
));
$
(
td
).
html
(
detail_btn
.
replace
(
"{{ DEFAULT_PK }}"
,
rowData
.
id
));
}},
}},
{
targets
:
4
,
createdCell
:
function
(
td
,
cellData
)
{
{
targets
:
4
,
createdCell
:
function
(
td
,
cellData
)
{
...
...
apps/users/urls/api_urls.py
View file @
722bf786
...
@@ -29,6 +29,8 @@ urlpatterns = [
...
@@ -29,6 +29,8 @@ urlpatterns = [
api
.
UserResetPKApi
.
as_view
(),
name
=
'user-public-key-reset'
),
api
.
UserResetPKApi
.
as_view
(),
name
=
'user-public-key-reset'
),
url
(
r'^v1/users/(?P<pk>[0-9a-zA-Z\-]{36})/pubkey/update/$'
,
url
(
r'^v1/users/(?P<pk>[0-9a-zA-Z\-]{36})/pubkey/update/$'
,
api
.
UserUpdatePKApi
.
as_view
(),
name
=
'user-public-key-update'
),
api
.
UserUpdatePKApi
.
as_view
(),
name
=
'user-public-key-update'
),
url
(
r'^v1/users/(?P<pk>[0-9a-zA-Z\-]{36})/unblock/$'
,
api
.
UserUnblockPKApi
.
as_view
(),
name
=
'user-unblock'
),
url
(
r'^v1/users/(?P<pk>[0-9a-zA-Z\-]{36})/groups/$'
,
url
(
r'^v1/users/(?P<pk>[0-9a-zA-Z\-]{36})/groups/$'
,
api
.
UserUpdateGroupApi
.
as_view
(),
name
=
'user-update-group'
),
api
.
UserUpdateGroupApi
.
as_view
(),
name
=
'user-update-group'
),
url
(
r'^v1/groups/(?P<pk>[0-9a-zA-Z\-]{36})/users/$'
,
url
(
r'^v1/groups/(?P<pk>[0-9a-zA-Z\-]{36})/users/$'
,
...
...
apps/users/urls/views_urls.py
View file @
722bf786
...
@@ -8,13 +8,13 @@ app_name = 'users'
...
@@ -8,13 +8,13 @@ app_name = 'users'
urlpatterns
=
[
urlpatterns
=
[
# Login view
# Login view
url
(
r'^login$'
,
views
.
UserLoginView
.
as_view
(),
name
=
'login'
),
url
(
r'^login
/
$'
,
views
.
UserLoginView
.
as_view
(),
name
=
'login'
),
url
(
r'^logout$'
,
views
.
UserLogoutView
.
as_view
(),
name
=
'logout'
),
url
(
r'^logout
/
$'
,
views
.
UserLogoutView
.
as_view
(),
name
=
'logout'
),
url
(
r'^login/otp$'
,
views
.
UserLoginOtpView
.
as_view
(),
name
=
'login-otp'
),
url
(
r'^login/otp
/
$'
,
views
.
UserLoginOtpView
.
as_view
(),
name
=
'login-otp'
),
url
(
r'^password/forgot$'
,
views
.
UserForgotPasswordView
.
as_view
(),
name
=
'forgot-password'
),
url
(
r'^password/forgot
/
$'
,
views
.
UserForgotPasswordView
.
as_view
(),
name
=
'forgot-password'
),
url
(
r'^password/forgot/sendmail-success$'
,
views
.
UserForgotPasswordSendmailSuccessView
.
as_view
(),
name
=
'forgot-password-sendmail-success'
),
url
(
r'^password/forgot/sendmail-success
/
$'
,
views
.
UserForgotPasswordSendmailSuccessView
.
as_view
(),
name
=
'forgot-password-sendmail-success'
),
url
(
r'^password/reset$'
,
views
.
UserResetPasswordView
.
as_view
(),
name
=
'reset-password'
),
url
(
r'^password/reset
/
$'
,
views
.
UserResetPasswordView
.
as_view
(),
name
=
'reset-password'
),
url
(
r'^password/reset/success$'
,
views
.
UserResetPasswordSuccessView
.
as_view
(),
name
=
'reset-password-success'
),
url
(
r'^password/reset/success
/
$'
,
views
.
UserResetPasswordSuccessView
.
as_view
(),
name
=
'reset-password-success'
),
# Profile
# Profile
url
(
r'^profile/$'
,
views
.
UserProfileView
.
as_view
(),
name
=
'user-profile'
),
url
(
r'^profile/$'
,
views
.
UserProfileView
.
as_view
(),
name
=
'user-profile'
),
...
@@ -29,23 +29,23 @@ urlpatterns = [
...
@@ -29,23 +29,23 @@ urlpatterns = [
url
(
r'^profile/otp/settings-success/$'
,
views
.
UserOtpSettingsSuccessView
.
as_view
(),
name
=
'user-otp-settings-success'
),
url
(
r'^profile/otp/settings-success/$'
,
views
.
UserOtpSettingsSuccessView
.
as_view
(),
name
=
'user-otp-settings-success'
),
# User view
# User view
url
(
r'^user$'
,
views
.
UserListView
.
as_view
(),
name
=
'user-list'
),
url
(
r'^user
/
$'
,
views
.
UserListView
.
as_view
(),
name
=
'user-list'
),
url
(
r'^user/export/'
,
views
.
UserExportView
.
as_view
(),
name
=
'user-export'
),
url
(
r'^user/export/
$
'
,
views
.
UserExportView
.
as_view
(),
name
=
'user-export'
),
url
(
r'^first-login/$'
,
views
.
UserFirstLoginView
.
as_view
(),
name
=
'user-first-login'
),
url
(
r'^first-login/$'
,
views
.
UserFirstLoginView
.
as_view
(),
name
=
'user-first-login'
),
url
(
r'^user/import/$'
,
views
.
UserBulkImportView
.
as_view
(),
name
=
'user-import'
),
url
(
r'^user/import/$'
,
views
.
UserBulkImportView
.
as_view
(),
name
=
'user-import'
),
url
(
r'^user/create$'
,
views
.
UserCreateView
.
as_view
(),
name
=
'user-create'
),
url
(
r'^user/create
/
$'
,
views
.
UserCreateView
.
as_view
(),
name
=
'user-create'
),
url
(
r'^user/(?P<pk>[0-9a-zA-Z\-]{36})/update$'
,
views
.
UserUpdateView
.
as_view
(),
name
=
'user-update'
),
url
(
r'^user/(?P<pk>[0-9a-zA-Z\-]{36})/update
/
$'
,
views
.
UserUpdateView
.
as_view
(),
name
=
'user-update'
),
url
(
r'^user/update$'
,
views
.
UserBulkUpdateView
.
as_view
(),
name
=
'user-bulk-update'
),
url
(
r'^user/update
/
$'
,
views
.
UserBulkUpdateView
.
as_view
(),
name
=
'user-bulk-update'
),
url
(
r'^user/(?P<pk>[0-9a-zA-Z\-]{36})$'
,
views
.
UserDetailView
.
as_view
(),
name
=
'user-detail'
),
url
(
r'^user/(?P<pk>[0-9a-zA-Z\-]{36})
/
$'
,
views
.
UserDetailView
.
as_view
(),
name
=
'user-detail'
),
url
(
r'^user/(?P<pk>[0-9a-zA-Z\-]{36})/assets'
,
views
.
UserGrantedAssetView
.
as_view
(),
name
=
'user-granted-asset'
),
url
(
r'^user/(?P<pk>[0-9a-zA-Z\-]{36})/assets
/$
'
,
views
.
UserGrantedAssetView
.
as_view
(),
name
=
'user-granted-asset'
),
url
(
r'^user/(?P<pk>[0-9a-zA-Z\-]{36})/login-history'
,
views
.
UserDetailView
.
as_view
(),
name
=
'user-login-history'
),
url
(
r'^user/(?P<pk>[0-9a-zA-Z\-]{36})/login-history
/$
'
,
views
.
UserDetailView
.
as_view
(),
name
=
'user-login-history'
),
# User group view
# User group view
url
(
r'^user-group$'
,
views
.
UserGroupListView
.
as_view
(),
name
=
'user-group-list'
),
url
(
r'^user-group
/
$'
,
views
.
UserGroupListView
.
as_view
(),
name
=
'user-group-list'
),
url
(
r'^user-group/(?P<pk>[0-9a-zA-Z\-]{36})$'
,
views
.
UserGroupDetailView
.
as_view
(),
name
=
'user-group-detail'
),
url
(
r'^user-group/(?P<pk>[0-9a-zA-Z\-]{36})
/
$'
,
views
.
UserGroupDetailView
.
as_view
(),
name
=
'user-group-detail'
),
url
(
r'^user-group/create$'
,
views
.
UserGroupCreateView
.
as_view
(),
name
=
'user-group-create'
),
url
(
r'^user-group/create
/
$'
,
views
.
UserGroupCreateView
.
as_view
(),
name
=
'user-group-create'
),
url
(
r'^user-group/(?P<pk>[0-9a-zA-Z\-]{36})/update$'
,
views
.
UserGroupUpdateView
.
as_view
(),
name
=
'user-group-update'
),
url
(
r'^user-group/(?P<pk>[0-9a-zA-Z\-]{36})/update
/
$'
,
views
.
UserGroupUpdateView
.
as_view
(),
name
=
'user-group-update'
),
url
(
r'^user-group/(?P<pk>[0-9a-zA-Z\-]{36})/assets'
,
views
.
UserGroupGrantedAssetView
.
as_view
(),
name
=
'user-group-granted-asset'
),
url
(
r'^user-group/(?P<pk>[0-9a-zA-Z\-]{36})/assets
/$
'
,
views
.
UserGroupGrantedAssetView
.
as_view
(),
name
=
'user-group-granted-asset'
),
# Login log
# Login log
url
(
r'^login-log/$'
,
views
.
LoginLogListView
.
as_view
(),
name
=
'login-log-list'
),
url
(
r'^login-log/$'
,
views
.
LoginLogListView
.
as_view
(),
name
=
'login-log-list'
),
...
...
apps/users/utils.py
View file @
722bf786
...
@@ -13,7 +13,7 @@ import ipaddress
...
@@ -13,7 +13,7 @@ import ipaddress
from
django.http
import
Http404
from
django.http
import
Http404
from
django.conf
import
settings
from
django.conf
import
settings
from
django.contrib.auth.mixins
import
UserPassesTestMixin
from
django.contrib.auth.mixins
import
UserPassesTestMixin
from
django.contrib.auth
import
authenticate
,
login
as
auth_login
from
django.contrib.auth
import
authenticate
from
django.utils.translation
import
ugettext
as
_
from
django.utils.translation
import
ugettext
as
_
from
django.core.cache
import
cache
from
django.core.cache
import
cache
...
@@ -200,16 +200,15 @@ def get_login_ip(request):
...
@@ -200,16 +200,15 @@ def get_login_ip(request):
return
login_ip
return
login_ip
def
write_login_log
(
username
,
type
=
''
,
ip
=
''
,
user_agent
=
''
):
def
write_login_log
(
*
args
,
**
kwargs
):
ip
=
kwargs
.
get
(
'ip'
,
''
)
if
not
(
ip
and
validate_ip
(
ip
)):
if
not
(
ip
and
validate_ip
(
ip
)):
ip
=
ip
[:
15
]
ip
=
ip
[:
15
]
city
=
"Unknown"
city
=
"Unknown"
else
:
else
:
city
=
get_ip_city
(
ip
)
city
=
get_ip_city
(
ip
)
LoginLog
.
objects
.
create
(
kwargs
.
update
({
'ip'
:
ip
,
'city'
:
city
})
username
=
username
,
type
=
type
,
LoginLog
.
objects
.
create
(
**
kwargs
)
ip
=
ip
,
city
=
city
,
user_agent
=
user_agent
)
def
get_ip_city
(
ip
,
timeout
=
10
):
def
get_ip_city
(
ip
,
timeout
=
10
):
...
@@ -332,3 +331,44 @@ def check_password_rules(password):
...
@@ -332,3 +331,44 @@ def check_password_rules(password):
match_obj
=
re
.
match
(
pattern
,
password
)
match_obj
=
re
.
match
(
pattern
,
password
)
return
bool
(
match_obj
)
return
bool
(
match_obj
)
def
set_user_login_failed_count_to_cache
(
key_limit
,
key_block
):
count
=
cache
.
get
(
key_limit
)
count
=
count
+
1
if
count
else
1
setting_limit_time
=
Setting
.
objects
.
filter
(
name
=
'SECURITY_LOGIN_LIMIT_TIME'
)
.
first
()
limit_time
=
setting_limit_time
.
cleaned_value
if
setting_limit_time
\
else
settings
.
DEFAULT_LOGIN_LIMIT_TIME
setting_limit_count
=
Setting
.
objects
.
filter
(
name
=
'SECURITY_LOGIN_LIMIT_COUNT'
)
.
first
()
limit_count
=
setting_limit_count
.
cleaned_value
if
setting_limit_count
\
else
settings
.
DEFAULT_LOGIN_LIMIT_COUNT
if
count
>=
limit_count
:
cache
.
set
(
key_block
,
1
,
int
(
limit_time
)
*
60
)
cache
.
set
(
key_limit
,
count
,
int
(
limit_time
)
*
60
)
def
is_block_login
(
key_limit
):
count
=
cache
.
get
(
key_limit
)
setting_limit_count
=
Setting
.
objects
.
filter
(
name
=
'SECURITY_LOGIN_LIMIT_COUNT'
)
.
first
()
limit_count
=
setting_limit_count
.
cleaned_value
if
setting_limit_count
\
else
settings
.
DEFAULT_LOGIN_LIMIT_COUNT
if
count
and
count
>=
limit_count
:
return
True
def
is_need_unblock
(
key_block
):
if
not
cache
.
get
(
key_block
):
return
False
return
True
apps/users/views/login.py
View file @
722bf786
...
@@ -25,8 +25,10 @@ from common.utils import get_object_or_none
...
@@ -25,8 +25,10 @@ from common.utils import get_object_or_none
from
common.mixins
import
DatetimeSearchMixin
,
AdminUserRequiredMixin
from
common.mixins
import
DatetimeSearchMixin
,
AdminUserRequiredMixin
from
common.models
import
Setting
from
common.models
import
Setting
from
..models
import
User
,
LoginLog
from
..models
import
User
,
LoginLog
from
..utils
import
send_reset_password_mail
,
check_otp_code
,
get_login_ip
,
redirect_user_first_login_or_index
,
\
from
..utils
import
send_reset_password_mail
,
check_otp_code
,
get_login_ip
,
\
get_user_or_tmp_user
,
set_tmp_user_to_cache
,
get_password_check_rules
,
check_password_rules
redirect_user_first_login_or_index
,
get_user_or_tmp_user
,
\
set_tmp_user_to_cache
,
get_password_check_rules
,
check_password_rules
,
\
is_block_login
,
set_user_login_failed_count_to_cache
from
..tasks
import
write_login_log_async
from
..tasks
import
write_login_log_async
from
..
import
forms
from
..
import
forms
...
@@ -47,7 +49,9 @@ class UserLoginView(FormView):
...
@@ -47,7 +49,9 @@ class UserLoginView(FormView):
form_class
=
forms
.
UserLoginForm
form_class
=
forms
.
UserLoginForm
form_class_captcha
=
forms
.
UserLoginCaptchaForm
form_class_captcha
=
forms
.
UserLoginCaptchaForm
redirect_field_name
=
'next'
redirect_field_name
=
'next'
key_prefix
=
"_LOGIN_INVALID_{}"
key_prefix_captcha
=
"_LOGIN_INVALID_{}"
key_prefix_limit
=
"_LOGIN_LIMIT_{}_{}"
key_prefix_block
=
"_LOGIN_BLOCK_{}"
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
if
request
.
user
.
is_staff
:
if
request
.
user
.
is_staff
:
...
@@ -57,6 +61,16 @@ class UserLoginView(FormView):
...
@@ -57,6 +61,16 @@ class UserLoginView(FormView):
request
.
session
.
set_test_cookie
()
request
.
session
.
set_test_cookie
()
return
super
()
.
get
(
request
,
*
args
,
**
kwargs
)
return
super
()
.
get
(
request
,
*
args
,
**
kwargs
)
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
# limit login authentication
ip
=
get_login_ip
(
request
)
username
=
self
.
request
.
POST
.
get
(
'username'
)
key_limit
=
self
.
key_prefix_limit
.
format
(
username
,
ip
)
if
is_block_login
(
key_limit
):
return
self
.
render_to_response
(
self
.
get_context_data
(
block_login
=
True
))
return
super
()
.
post
(
request
,
*
args
,
**
kwargs
)
def
form_valid
(
self
,
form
):
def
form_valid
(
self
,
form
):
if
not
self
.
request
.
session
.
test_cookie_worked
():
if
not
self
.
request
.
session
.
test_cookie_worked
():
return
HttpResponse
(
_
(
"Please enable cookies and try again."
))
return
HttpResponse
(
_
(
"Please enable cookies and try again."
))
...
@@ -65,8 +79,24 @@ class UserLoginView(FormView):
...
@@ -65,8 +79,24 @@ class UserLoginView(FormView):
return
redirect
(
self
.
get_success_url
())
return
redirect
(
self
.
get_success_url
())
def
form_invalid
(
self
,
form
):
def
form_invalid
(
self
,
form
):
# write login failed log
username
=
form
.
cleaned_data
.
get
(
'username'
)
data
=
{
'username'
:
username
,
'mfa'
:
LoginLog
.
MFA_UNKNOWN
,
'reason'
:
LoginLog
.
REASON_PASSWORD
,
'status'
:
False
}
self
.
write_login_log
(
data
)
# limit user login failed count
ip
=
get_login_ip
(
self
.
request
)
ip
=
get_login_ip
(
self
.
request
)
cache
.
set
(
self
.
key_prefix
.
format
(
ip
),
1
,
3600
)
key_limit
=
self
.
key_prefix_limit
.
format
(
username
,
ip
)
key_block
=
self
.
key_prefix_block
.
format
(
username
)
set_user_login_failed_count_to_cache
(
key_limit
,
key_block
)
# show captcha
cache
.
set
(
self
.
key_prefix_captcha
.
format
(
ip
),
1
,
3600
)
old_form
=
form
old_form
=
form
form
=
self
.
form_class_captcha
(
data
=
form
.
data
)
form
=
self
.
form_class_captcha
(
data
=
form
.
data
)
form
.
_errors
=
old_form
.
errors
form
.
_errors
=
old_form
.
errors
...
@@ -74,7 +104,7 @@ class UserLoginView(FormView):
...
@@ -74,7 +104,7 @@ class UserLoginView(FormView):
def
get_form_class
(
self
):
def
get_form_class
(
self
):
ip
=
get_login_ip
(
self
.
request
)
ip
=
get_login_ip
(
self
.
request
)
if
cache
.
get
(
self
.
key_prefix
.
format
(
ip
)):
if
cache
.
get
(
self
.
key_prefix
_captcha
.
format
(
ip
)):
return
self
.
form_class_captcha
return
self
.
form_class_captcha
else
:
else
:
return
self
.
form_class
return
self
.
form_class
...
@@ -91,7 +121,13 @@ class UserLoginView(FormView):
...
@@ -91,7 +121,13 @@ class UserLoginView(FormView):
elif
not
user
.
otp_enabled
:
elif
not
user
.
otp_enabled
:
# 0 & T,F
# 0 & T,F
auth_login
(
self
.
request
,
user
)
auth_login
(
self
.
request
,
user
)
self
.
write_login_log
()
data
=
{
'username'
:
self
.
request
.
user
.
username
,
'mfa'
:
int
(
self
.
request
.
user
.
otp_enabled
),
'reason'
:
LoginLog
.
REASON_NOTHING
,
'status'
:
True
}
self
.
write_login_log
(
data
)
return
redirect_user_first_login_or_index
(
self
.
request
,
self
.
redirect_field_name
)
return
redirect_user_first_login_or_index
(
self
.
request
,
self
.
redirect_field_name
)
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
...
@@ -101,13 +137,16 @@ class UserLoginView(FormView):
...
@@ -101,13 +137,16 @@ class UserLoginView(FormView):
kwargs
.
update
(
context
)
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
return
super
()
.
get_context_data
(
**
kwargs
)
def
write_login_log
(
self
):
def
write_login_log
(
self
,
data
):
login_ip
=
get_login_ip
(
self
.
request
)
login_ip
=
get_login_ip
(
self
.
request
)
user_agent
=
self
.
request
.
META
.
get
(
'HTTP_USER_AGENT'
,
''
)
user_agent
=
self
.
request
.
META
.
get
(
'HTTP_USER_AGENT'
,
''
)
write_login_log_async
.
delay
(
tmp_data
=
{
self
.
request
.
user
.
username
,
type
=
'W'
,
'ip'
:
login_ip
,
ip
=
login_ip
,
user_agent
=
user_agent
'type'
:
'W'
,
)
'user_agent'
:
user_agent
}
data
.
update
(
tmp_data
)
write_login_log_async
.
delay
(
**
data
)
class
UserLoginOtpView
(
FormView
):
class
UserLoginOtpView
(
FormView
):
...
@@ -122,22 +161,38 @@ class UserLoginOtpView(FormView):
...
@@ -122,22 +161,38 @@ class UserLoginOtpView(FormView):
if
check_otp_code
(
otp_secret_key
,
otp_code
):
if
check_otp_code
(
otp_secret_key
,
otp_code
):
auth_login
(
self
.
request
,
user
)
auth_login
(
self
.
request
,
user
)
self
.
write_login_log
()
data
=
{
'username'
:
self
.
request
.
user
.
username
,
'mfa'
:
int
(
self
.
request
.
user
.
otp_enabled
),
'reason'
:
LoginLog
.
REASON_NOTHING
,
'status'
:
True
}
self
.
write_login_log
(
data
)
return
redirect
(
self
.
get_success_url
())
return
redirect
(
self
.
get_success_url
())
else
:
else
:
data
=
{
'username'
:
user
.
username
,
'mfa'
:
int
(
user
.
otp_enabled
),
'reason'
:
LoginLog
.
REASON_MFA
,
'status'
:
False
}
self
.
write_login_log
(
data
)
form
.
add_error
(
'otp_code'
,
_
(
'MFA code invalid'
))
form
.
add_error
(
'otp_code'
,
_
(
'MFA code invalid'
))
return
super
()
.
form_invalid
(
form
)
return
super
()
.
form_invalid
(
form
)
def
get_success_url
(
self
):
def
get_success_url
(
self
):
return
redirect_user_first_login_or_index
(
self
.
request
,
self
.
redirect_field_name
)
return
redirect_user_first_login_or_index
(
self
.
request
,
self
.
redirect_field_name
)
def
write_login_log
(
self
):
def
write_login_log
(
self
,
data
):
login_ip
=
get_login_ip
(
self
.
request
)
login_ip
=
get_login_ip
(
self
.
request
)
user_agent
=
self
.
request
.
META
.
get
(
'HTTP_USER_AGENT'
,
''
)
user_agent
=
self
.
request
.
META
.
get
(
'HTTP_USER_AGENT'
,
''
)
write_login_log_async
.
delay
(
tmp_data
=
{
self
.
request
.
user
.
username
,
type
=
'W'
,
'ip'
:
login_ip
,
ip
=
login_ip
,
user_agent
=
user_agent
'type'
:
'W'
,
)
'user_agent'
:
user_agent
}
data
.
update
(
tmp_data
)
write_login_log_async
.
delay
(
**
data
)
@method_decorator
(
never_cache
,
name
=
'dispatch'
)
@method_decorator
(
never_cache
,
name
=
'dispatch'
)
...
...
apps/users/views/user.py
View file @
722bf786
...
@@ -36,7 +36,9 @@ from common.utils import get_logger, get_object_or_none, is_uuid, ssh_key_gen
...
@@ -36,7 +36,9 @@ from common.utils import get_logger, get_object_or_none, is_uuid, ssh_key_gen
from
common.models
import
Setting
from
common.models
import
Setting
from
..
import
forms
from
..
import
forms
from
..models
import
User
,
UserGroup
from
..models
import
User
,
UserGroup
from
..utils
import
AdminUserRequiredMixin
,
generate_otp_uri
,
check_otp_code
,
get_user_or_tmp_user
,
get_password_check_rules
,
check_password_rules
from
..utils
import
AdminUserRequiredMixin
,
generate_otp_uri
,
check_otp_code
,
\
get_user_or_tmp_user
,
get_password_check_rules
,
check_password_rules
,
\
is_need_unblock
from
..signals
import
post_user_create
from
..signals
import
post_user_create
from
..tasks
import
write_login_log_async
from
..tasks
import
write_login_log_async
...
@@ -168,13 +170,17 @@ class UserDetailView(AdminUserRequiredMixin, DetailView):
...
@@ -168,13 +170,17 @@ class UserDetailView(AdminUserRequiredMixin, DetailView):
model
=
User
model
=
User
template_name
=
'users/user_detail.html'
template_name
=
'users/user_detail.html'
context_object_name
=
"user_object"
context_object_name
=
"user_object"
key_prefix_block
=
"_LOGIN_BLOCK_{}"
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
user
=
self
.
get_object
()
key_block
=
self
.
key_prefix_block
.
format
(
user
.
username
)
groups
=
UserGroup
.
objects
.
exclude
(
id__in
=
self
.
object
.
groups
.
all
())
groups
=
UserGroup
.
objects
.
exclude
(
id__in
=
self
.
object
.
groups
.
all
())
context
=
{
context
=
{
'app'
:
_
(
'Users'
),
'app'
:
_
(
'Users'
),
'action'
:
_
(
'User detail'
),
'action'
:
_
(
'User detail'
),
'groups'
:
groups
'groups'
:
groups
,
'unblock'
:
is_need_unblock
(
key_block
),
}
}
kwargs
.
update
(
context
)
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
return
super
()
.
get_context_data
(
**
kwargs
)
...
...
config_example.py
View file @
722bf786
...
@@ -21,10 +21,10 @@ class Config:
...
@@ -21,10 +21,10 @@ class Config:
ALLOWED_HOSTS
=
[
'*'
]
ALLOWED_HOSTS
=
[
'*'
]
# Development env open this, when error occur display the full process track, Production disable it
# Development env open this, when error occur display the full process track, Production disable it
DEBUG
=
True
DEBUG
=
os
.
environ
.
get
(
"DEBUG"
)
or
True
# DEBUG, INFO, WARNING, ERROR, CRITICAL can set. See https://docs.djangoproject.com/en/1.10/topics/logging/
# DEBUG, INFO, WARNING, ERROR, CRITICAL can set. See https://docs.djangoproject.com/en/1.10/topics/logging/
LOG_LEVEL
=
'DEBUG'
LOG_LEVEL
=
os
.
environ
.
get
(
"LOG_LEVEL"
)
or
'DEBUG'
LOG_DIR
=
os
.
path
.
join
(
BASE_DIR
,
'logs'
)
LOG_DIR
=
os
.
path
.
join
(
BASE_DIR
,
'logs'
)
# Database setting, Support sqlite3, mysql, postgres ....
# Database setting, Support sqlite3, mysql, postgres ....
...
@@ -35,12 +35,12 @@ class Config:
...
@@ -35,12 +35,12 @@ class Config:
DB_NAME
=
os
.
path
.
join
(
BASE_DIR
,
'data'
,
'db.sqlite3'
)
DB_NAME
=
os
.
path
.
join
(
BASE_DIR
,
'data'
,
'db.sqlite3'
)
# MySQL or postgres setting like:
# MySQL or postgres setting like:
# DB_ENGINE = 'mysql'
# DB_ENGINE =
os.environ.get("DB_ENGINE") or
'mysql'
# DB_HOST = '127.0.0.1'
# DB_HOST =
os.environ.get("DB_HOST") or
'127.0.0.1'
# DB_PORT = 3306
# DB_PORT =
os.environ.get("DB_PORT") or
3306
# DB_USER =
'root
'
# DB_USER =
os.environ.get("DB_USER") or 'jumpserver
'
# DB_PASSWORD =
'
'
# DB_PASSWORD =
os.environ.get("DB_PASSWORD") or 'weakPassword
'
# DB_NAME = 'jumpserver'
# DB_NAME =
os.environ.get("DB_NAME") or
'jumpserver'
# When Django start it will bind this host and port
# When Django start it will bind this host and port
# ./manage.py runserver 127.0.0.1:8080
# ./manage.py runserver 127.0.0.1:8080
...
@@ -48,9 +48,11 @@ class Config:
...
@@ -48,9 +48,11 @@ class Config:
HTTP_LISTEN_PORT
=
8080
HTTP_LISTEN_PORT
=
8080
# Use Redis as broker for celery and web socket
# Use Redis as broker for celery and web socket
REDIS_HOST
=
'127.0.0.1'
REDIS_HOST
=
os
.
environ
.
get
(
"REDIS_HOST"
)
or
'127.0.0.1'
REDIS_PORT
=
6379
REDIS_PORT
=
os
.
environ
.
get
(
"REDIS_PORT"
)
or
6379
REDIS_PASSWORD
=
''
REDIS_PASSWORD
=
os
.
environ
.
get
(
"REDIS_PASSWORD"
)
or
''
REDIS_DB_CELERY
=
os
.
environ
.
get
(
'REDIS_DB'
)
or
3
REDIS_DB_CACHE
=
os
.
environ
.
get
(
'REDIS_DB'
)
or
4
def
__init__
(
self
):
def
__init__
(
self
):
pass
pass
...
...
requirements/deb_requirements.txt
View file @
722bf786
libtiff5-dev libjpeg8-dev zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.5-dev tk8.5-dev python-tk python-dev openssl libssl-dev libldap2-dev libsasl2-dev sqlite gcc automake
libtiff5-dev libjpeg8-dev zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.5-dev tk8.5-dev python-tk python-dev openssl libssl-dev libldap2-dev libsasl2-dev sqlite gcc automake
libkrb5-dev
requirements/requirements.txt
View file @
722bf786
...
@@ -61,7 +61,7 @@ pytz==2018.3
...
@@ -61,7 +61,7 @@ pytz==2018.3
PyYAML==3.12
PyYAML==3.12
redis==2.10.6
redis==2.10.6
requests==2.18.4
requests==2.18.4
jms-storage==0.0.1
7
jms-storage==0.0.1
8
s3transfer==0.1.13
s3transfer==0.1.13
simplejson==3.13.2
simplejson==3.13.2
six==1.11.0
six==1.11.0
...
...
utils/make_migrations.sh
View file @
722bf786
...
@@ -4,3 +4,5 @@
...
@@ -4,3 +4,5 @@
python3 ../apps/manage.py makemigrations
python3 ../apps/manage.py makemigrations
python3 ../apps/manage.py migrate
python3 ../apps/manage.py migrate
python3 ../apps/manage.py makemigrations
--merge
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