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
a5b874e2
Commit
a5b874e2
authored
May 24, 2019
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Update] 改密支持windows
parent
75fb37d2
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
649 additions
and
252 deletions
+649
-252
asset.py
apps/assets/api/asset.py
+3
-2
asset.py
apps/assets/forms/asset.py
+27
-11
0027_auto_20190521_1703.py
apps/assets/migrations/0027_auto_20190521_1703.py
+5
-0
0028_protocol.py
apps/assets/migrations/0028_protocol.py
+29
-0
0029_auto_20190522_1114.py
apps/assets/migrations/0029_auto_20190522_1114.py
+22
-0
__init__.py
apps/assets/models/__init__.py
+0
-1
asset.py
apps/assets/models/asset.py
+31
-14
asset.py
apps/assets/serializers/asset.py
+70
-16
signals_handler.py
apps/assets/signals_handler.py
+4
-0
asset_create.html
apps/assets/templates/assets/asset_create.html
+153
-14
asset_update.html
apps/assets/templates/assets/asset_update.html
+41
-84
asset.py
apps/assets/views/asset.py
+32
-2
decorator.py
apps/common/decorator.py
+12
-0
mixins.py
apps/common/mixins.py
+24
-0
validators.py
apps/common/validators.py
+18
-2
conf.py
apps/jumpserver/conf.py
+4
-1
django.mo
apps/locale/zh/LC_MESSAGES/django.mo
+0
-0
django.po
apps/locale/zh/LC_MESSAGES/django.po
+129
-98
mixins.py
apps/orgs/mixins.py
+13
-0
hands.py
apps/perms/hands.py
+2
-1
remote_app_permission.py
apps/perms/views/remote_app_permission.py
+1
-2
jumpserver.css
apps/static/css/jumpserver.css
+13
-2
jumpserver.js
apps/static/js/jumpserver.js
+16
-2
No files found.
apps/assets/api/asset.py
View file @
a5b874e2
...
@@ -16,7 +16,7 @@ from django.urls import reverse_lazy
...
@@ -16,7 +16,7 @@ from django.urls import reverse_lazy
from
django.core.cache
import
cache
from
django.core.cache
import
cache
from
django.db.models
import
Q
from
django.db.models
import
Q
from
common.mixins
import
IDInCacheFilterMixin
from
common.mixins
import
IDInCacheFilterMixin
,
ApiMessageMixin
from
common.utils
import
get_logger
,
get_object_or_none
from
common.utils
import
get_logger
,
get_object_or_none
from
common.permissions
import
IsOrgAdmin
,
IsOrgAdminOrAppUser
from
common.permissions
import
IsOrgAdmin
,
IsOrgAdminOrAppUser
...
@@ -36,7 +36,7 @@ __all__ = [
...
@@ -36,7 +36,7 @@ __all__ = [
]
]
class
AssetViewSet
(
IDInCacheFilterMixin
,
LabelFilter
,
BulkModelViewSet
):
class
AssetViewSet
(
IDInCacheFilterMixin
,
LabelFilter
,
ApiMessageMixin
,
BulkModelViewSet
):
"""
"""
API endpoint that allows Asset to be viewed or edited.
API endpoint that allows Asset to be viewed or edited.
"""
"""
...
@@ -47,6 +47,7 @@ class AssetViewSet(IDInCacheFilterMixin, LabelFilter, BulkModelViewSet):
...
@@ -47,6 +47,7 @@ class AssetViewSet(IDInCacheFilterMixin, LabelFilter, BulkModelViewSet):
serializer_class
=
serializers
.
AssetSerializer
serializer_class
=
serializers
.
AssetSerializer
pagination_class
=
LimitOffsetPagination
pagination_class
=
LimitOffsetPagination
permission_classes
=
(
IsOrgAdminOrAppUser
,)
permission_classes
=
(
IsOrgAdminOrAppUser
,)
success_message
=
_
(
"
%(hostname)
s was
%(action)
s successfully"
)
def
set_assets_node
(
self
,
assets
):
def
set_assets_node
(
self
,
assets
):
if
not
isinstance
(
assets
,
list
):
if
not
isinstance
(
assets
,
list
):
...
...
apps/assets/forms/asset.py
View file @
a5b874e2
...
@@ -6,21 +6,39 @@ from django.utils.translation import gettext_lazy as _
...
@@ -6,21 +6,39 @@ from django.utils.translation import gettext_lazy as _
from
common.utils
import
get_logger
from
common.utils
import
get_logger
from
orgs.mixins
import
OrgModelForm
from
orgs.mixins
import
OrgModelForm
from
..models
import
Asset
,
AdminUser
from
..models
import
Asset
,
AdminUser
,
Protocol
logger
=
get_logger
(
__file__
)
logger
=
get_logger
(
__file__
)
__all__
=
[
'AssetCreateForm'
,
'AssetUpdateForm'
,
'AssetBulkUpdateForm'
]
__all__
=
[
'AssetCreateForm'
,
'AssetUpdateForm'
,
'AssetBulkUpdateForm'
,
'ProtocolForm'
]
class
ProtocolForm
(
forms
.
ModelForm
):
class
Meta
:
model
=
Protocol
fields
=
[
'name'
,
'port'
]
widgets
=
{
'name'
:
forms
.
Select
(
attrs
=
{
'class'
:
'form-control protocol-name'
}),
'port'
:
forms
.
TextInput
(
attrs
=
{
'class'
:
'form-control protocol-port'
}),
}
class
AssetCreateForm
(
OrgModelForm
):
class
AssetCreateForm
(
OrgModelForm
):
PROTOCOL_CHOICES
=
Protocol
.
PROTOCOL_CHOICES
class
Meta
:
class
Meta
:
model
=
Asset
model
=
Asset
fields
=
[
fields
=
[
'hostname'
,
'ip'
,
'public_ip'
,
'p
ort'
,
'comment'
,
'hostname'
,
'ip'
,
'public_ip'
,
'p
rotocols'
,
'comment'
,
'nodes'
,
'is_active'
,
'admin_user'
,
'labels'
,
'platform'
,
'nodes'
,
'is_active'
,
'admin_user'
,
'labels'
,
'platform'
,
'domain'
,
'protocol'
,
'domain'
,
]
]
widgets
=
{
widgets
=
{
'nodes'
:
forms
.
SelectMultiple
(
attrs
=
{
'nodes'
:
forms
.
SelectMultiple
(
attrs
=
{
...
@@ -32,7 +50,6 @@ class AssetCreateForm(OrgModelForm):
...
@@ -32,7 +50,6 @@ class AssetCreateForm(OrgModelForm):
'labels'
:
forms
.
SelectMultiple
(
attrs
=
{
'labels'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Label'
)
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Label'
)
}),
}),
'port'
:
forms
.
TextInput
(),
'domain'
:
forms
.
Select
(
attrs
=
{
'domain'
:
forms
.
Select
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Domain'
)
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Domain'
)
}),
}),
...
@@ -54,9 +71,9 @@ class AssetUpdateForm(OrgModelForm):
...
@@ -54,9 +71,9 @@ class AssetUpdateForm(OrgModelForm):
class
Meta
:
class
Meta
:
model
=
Asset
model
=
Asset
fields
=
[
fields
=
[
'hostname'
,
'ip'
,
'p
ort
'
,
'nodes'
,
'is_active'
,
'platform'
,
'hostname'
,
'ip'
,
'p
rotocols
'
,
'nodes'
,
'is_active'
,
'platform'
,
'public_ip'
,
'number'
,
'comment'
,
'admin_user'
,
'labels'
,
'public_ip'
,
'number'
,
'comment'
,
'admin_user'
,
'labels'
,
'domain'
,
'protocol'
,
'domain'
,
]
]
widgets
=
{
widgets
=
{
'nodes'
:
forms
.
SelectMultiple
(
attrs
=
{
'nodes'
:
forms
.
SelectMultiple
(
attrs
=
{
...
@@ -68,7 +85,6 @@ class AssetUpdateForm(OrgModelForm):
...
@@ -68,7 +85,6 @@ class AssetUpdateForm(OrgModelForm):
'labels'
:
forms
.
SelectMultiple
(
attrs
=
{
'labels'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Label'
)
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Label'
)
}),
}),
'port'
:
forms
.
TextInput
(),
'domain'
:
forms
.
Select
(
attrs
=
{
'domain'
:
forms
.
Select
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Domain'
)
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Domain'
)
}),
}),
...
@@ -101,8 +117,8 @@ class AssetBulkUpdateForm(OrgModelForm):
...
@@ -101,8 +117,8 @@ class AssetBulkUpdateForm(OrgModelForm):
class
Meta
:
class
Meta
:
model
=
Asset
model
=
Asset
fields
=
[
fields
=
[
'assets'
,
'
port'
,
'
admin_user'
,
'labels'
,
'platform'
,
'assets'
,
'admin_user'
,
'labels'
,
'platform'
,
'
protocol'
,
'
domain'
,
'domain'
,
]
]
widgets
=
{
widgets
=
{
'labels'
:
forms
.
SelectMultiple
(
'labels'
:
forms
.
SelectMultiple
(
...
...
apps/assets/migrations/0027_auto_20190521_1703.py
View file @
a5b874e2
...
@@ -15,4 +15,9 @@ class Migration(migrations.Migration):
...
@@ -15,4 +15,9 @@ class Migration(migrations.Migration):
name
=
'ip'
,
name
=
'ip'
,
field
=
models
.
CharField
(
db_index
=
True
,
max_length
=
128
,
verbose_name
=
'IP'
),
field
=
models
.
CharField
(
db_index
=
True
,
max_length
=
128
,
verbose_name
=
'IP'
),
),
),
migrations
.
AlterField
(
model_name
=
'asset'
,
name
=
'public_ip'
,
field
=
models
.
CharField
(
blank
=
True
,
max_length
=
128
,
null
=
True
,
verbose_name
=
'Public IP'
),
),
]
]
apps/assets/migrations/0028_protocol.py
0 → 100644
View file @
a5b874e2
# Generated by Django 2.1.7 on 2019-05-22 02:58
import
django.core.validators
from
django.db
import
migrations
,
models
import
uuid
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'assets'
,
'0027_auto_20190521_1703'
),
]
operations
=
[
migrations
.
CreateModel
(
name
=
'Protocol'
,
fields
=
[
(
'id'
,
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
,
serialize
=
False
)),
(
'name'
,
models
.
CharField
(
choices
=
[(
'ssh'
,
'ssh'
),
(
'rdp'
,
'rdp'
),
(
'telnet'
,
'telnet (beta)'
),
(
'vnc'
,
'vnc'
)],
default
=
'ssh'
,
max_length
=
16
,
verbose_name
=
'Name'
)),
(
'port'
,
models
.
IntegerField
(
default
=
22
,
validators
=
[
django
.
core
.
validators
.
MaxValueValidator
(
65535
),
django
.
core
.
validators
.
MinValueValidator
(
1
)],
verbose_name
=
'Port'
)),
],
),
migrations
.
AddField
(
model_name
=
'asset'
,
name
=
'protocols'
,
field
=
models
.
ManyToManyField
(
to
=
'assets.Protocol'
,
verbose_name
=
'Protocol'
),
),
]
apps/assets/migrations/0029_auto_20190522_1114.py
0 → 100644
View file @
a5b874e2
# Generated by Django 2.1.7 on 2019-05-22 03:14
from
django.db
import
migrations
def
migrate_assets_protocol
(
apps
,
schema_editor
):
asset_model
=
apps
.
get_model
(
"assets"
,
"Asset"
)
db_alias
=
schema_editor
.
connection
.
alias
assets
=
asset_model
.
objects
.
using
(
db_alias
)
.
all
()
for
asset
in
assets
:
asset
.
protocols
.
create
(
name
=
asset
.
protocol
,
port
=
asset
.
port
)
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'assets'
,
'0028_protocol'
),
]
operations
=
[
migrations
.
RunPython
(
migrate_assets_protocol
),
]
apps/assets/models/__init__.py
View file @
a5b874e2
...
@@ -8,4 +8,3 @@ from .asset import *
...
@@ -8,4 +8,3 @@ from .asset import *
from
.cmd_filter
import
*
from
.cmd_filter
import
*
from
.utils
import
*
from
.utils
import
*
from
.authbook
import
*
from
.authbook
import
*
from
applications.models.remote_app
import
*
apps/assets/models/asset.py
View file @
a5b874e2
...
@@ -12,11 +12,12 @@ from django.db import models
...
@@ -12,11 +12,12 @@ from django.db import models
from
django.db.models
import
Q
from
django.db.models
import
Q
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.core.cache
import
cache
from
django.core.cache
import
cache
from
django.core.validators
import
MinValueValidator
,
MaxValueValidator
from
.user
import
AdminUser
,
SystemUser
from
.user
import
AdminUser
,
SystemUser
from
orgs.mixins
import
OrgModelMixin
,
OrgManager
from
orgs.mixins
import
OrgModelMixin
,
OrgManager
__all__
=
[
'Asset'
]
__all__
=
[
'Asset'
,
'Protocol'
]
logger
=
logging
.
getLogger
(
__name__
)
logger
=
logging
.
getLogger
(
__name__
)
...
@@ -47,6 +48,29 @@ class AssetQuerySet(models.QuerySet):
...
@@ -47,6 +48,29 @@ class AssetQuerySet(models.QuerySet):
return
self
.
active
()
return
self
.
active
()
class
Protocol
(
models
.
Model
):
PROTOCOL_SSH
=
'ssh'
PROTOCOL_RDP
=
'rdp'
PROTOCOL_TELNET
=
'telnet'
PROTOCOL_VNC
=
'vnc'
PROTOCOL_CHOICES
=
(
(
PROTOCOL_SSH
,
'ssh'
),
(
PROTOCOL_RDP
,
'rdp'
),
(
PROTOCOL_TELNET
,
'telnet (beta)'
),
(
PROTOCOL_VNC
,
'vnc'
),
)
PORT_VALIDATORS
=
[
MaxValueValidator
(
65535
),
MinValueValidator
(
1
)]
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
name
=
models
.
CharField
(
max_length
=
16
,
choices
=
PROTOCOL_CHOICES
,
default
=
PROTOCOL_SSH
,
verbose_name
=
_
(
"Name"
))
port
=
models
.
IntegerField
(
default
=
22
,
verbose_name
=
_
(
"Port"
),
validators
=
PORT_VALIDATORS
)
def
__str__
(
self
):
return
"{}:{}"
.
format
(
self
.
name
,
self
.
port
)
class
Asset
(
OrgModelMixin
):
class
Asset
(
OrgModelMixin
):
# Important
# Important
PLATFORM_CHOICES
=
(
PLATFORM_CHOICES
=
(
...
@@ -59,22 +83,15 @@ class Asset(OrgModelMixin):
...
@@ -59,22 +83,15 @@ class Asset(OrgModelMixin):
(
'Other'
,
'Other'
),
(
'Other'
,
'Other'
),
)
)
PROTOCOL_SSH
=
'ssh'
PROTOCOL_RDP
=
'rdp'
PROTOCOL_TELNET
=
'telnet'
PROTOCOL_VNC
=
'vnc'
PROTOCOL_CHOICES
=
(
(
PROTOCOL_SSH
,
'ssh'
),
(
PROTOCOL_RDP
,
'rdp'
),
(
PROTOCOL_TELNET
,
'telnet (beta)'
),
(
PROTOCOL_VNC
,
'vnc'
),
)
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
ip
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
'IP'
),
db_index
=
True
)
ip
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
'IP'
),
db_index
=
True
)
hostname
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
'Hostname'
))
hostname
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
'Hostname'
))
protocol
=
models
.
CharField
(
max_length
=
128
,
default
=
PROTOCOL_SSH
,
choices
=
PROTOCOL_CHOICES
,
verbose_name
=
_
(
'Protocol'
))
protocol
=
models
.
CharField
(
max_length
=
128
,
default
=
Protocol
.
PROTOCOL_SSH
,
choices
=
Protocol
.
PROTOCOL_CHOICES
,
verbose_name
=
_
(
'Protocol'
))
port
=
models
.
IntegerField
(
default
=
22
,
verbose_name
=
_
(
'Port'
))
port
=
models
.
IntegerField
(
default
=
22
,
verbose_name
=
_
(
'Port'
))
protocols
=
models
.
ManyToManyField
(
'Protocol'
,
verbose_name
=
_
(
"Protocol"
))
platform
=
models
.
CharField
(
max_length
=
128
,
choices
=
PLATFORM_CHOICES
,
default
=
'Linux'
,
verbose_name
=
_
(
'Platform'
))
platform
=
models
.
CharField
(
max_length
=
128
,
choices
=
PLATFORM_CHOICES
,
default
=
'Linux'
,
verbose_name
=
_
(
'Platform'
))
domain
=
models
.
ForeignKey
(
"assets.Domain"
,
null
=
True
,
blank
=
True
,
related_name
=
'assets'
,
verbose_name
=
_
(
"Domain"
),
on_delete
=
models
.
SET_NULL
)
domain
=
models
.
ForeignKey
(
"assets.Domain"
,
null
=
True
,
blank
=
True
,
related_name
=
'assets'
,
verbose_name
=
_
(
"Domain"
),
on_delete
=
models
.
SET_NULL
)
nodes
=
models
.
ManyToManyField
(
'assets.Node'
,
default
=
default_node
,
related_name
=
'assets'
,
verbose_name
=
_
(
"Nodes"
))
nodes
=
models
.
ManyToManyField
(
'assets.Node'
,
default
=
default_node
,
related_name
=
'assets'
,
verbose_name
=
_
(
"Nodes"
))
...
@@ -84,7 +101,7 @@ class Asset(OrgModelMixin):
...
@@ -84,7 +101,7 @@ class Asset(OrgModelMixin):
admin_user
=
models
.
ForeignKey
(
'assets.AdminUser'
,
on_delete
=
models
.
PROTECT
,
null
=
True
,
verbose_name
=
_
(
"Admin user"
))
admin_user
=
models
.
ForeignKey
(
'assets.AdminUser'
,
on_delete
=
models
.
PROTECT
,
null
=
True
,
verbose_name
=
_
(
"Admin user"
))
# Some information
# Some information
public_ip
=
models
.
GenericIPAddressField
(
max_length
=
32
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Public IP'
))
public_ip
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Public IP'
))
number
=
models
.
CharField
(
max_length
=
32
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Asset number'
))
number
=
models
.
CharField
(
max_length
=
32
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Asset number'
))
# Collect
# Collect
...
...
apps/assets/serializers/asset.py
View file @
a5b874e2
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
#
#
from
rest_framework
import
serializers
from
rest_framework
import
serializers
from
rest_framework.validators
import
ValidationError
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.translation
import
ugettext_lazy
as
_
from
orgs.mixins
import
OrgResourceSerializerMixin
from
orgs.mixins
import
OrgResourceSerializerMixin
from
common.mixins
import
BulkSerializerMixin
from
common.mixins
import
BulkSerializerMixin
from
common.serializers
import
AdaptedBulkListSerializer
from
common.serializers
import
AdaptedBulkListSerializer
from
..models
import
Asset
from
common.validators
import
ProjectUniqueValidator
from
..models
import
Asset
,
Protocol
from
.system_user
import
AssetSystemUserSerializer
from
.system_user
import
AssetSystemUserSerializer
__all__
=
[
__all__
=
[
...
@@ -16,25 +18,32 @@ __all__ = [
...
@@ -16,25 +18,32 @@ __all__ = [
]
]
class
AssetSerializer
(
BulkSerializerMixin
,
serializers
.
ModelSerializer
,
OrgResourceSerializerMixin
):
class
ProtocolSerializer
(
serializers
.
ModelSerializer
):
class
Meta
:
model
=
Protocol
fields
=
[
"name"
,
"port"
]
class
AssetSerializer
(
BulkSerializerMixin
,
OrgResourceSerializerMixin
,
serializers
.
ModelSerializer
):
protocols
=
ProtocolSerializer
(
many
=
True
)
"""
"""
资产的数据结构
资产的数据结构
"""
"""
class
Meta
:
class
Meta
:
model
=
Asset
model
=
Asset
list_serializer_class
=
AdaptedBulkListSerializer
list_serializer_class
=
AdaptedBulkListSerializer
# validators = [] # 解决批量导入时unique_together字段校验失败
fields
=
[
fields
=
[
'id'
,
'org_id'
,
'org_name'
,
'ip'
,
'hostname'
,
'protocol'
,
'port'
,
'id'
,
'org_id'
,
'org_name'
,
'ip'
,
'hostname'
,
'protocol'
,
'port'
,
'p
latform'
,
'is_active'
,
'public_ip'
,
'domain'
,
'admin_user
'
,
'p
rotocols'
,
'platform'
,
'is_active'
,
'public_ip'
,
'domain
'
,
'nodes'
,
'labels'
,
'number'
,
'vendor'
,
'model'
,
'sn'
,
'
admin_user'
,
'
nodes'
,
'labels'
,
'number'
,
'vendor'
,
'model'
,
'sn'
,
'cpu_model'
,
'cpu_count'
,
'cpu_cores'
,
'cpu_vcpus'
,
'memory'
,
'cpu_model'
,
'cpu_count'
,
'cpu_cores'
,
'cpu_vcpus'
,
'memory'
,
'disk_total'
,
'disk_info'
,
'os'
,
'os_version'
,
'os_arch'
,
'disk_total'
,
'disk_info'
,
'os'
,
'os_version'
,
'os_arch'
,
'hostname_raw'
,
'comment'
,
'created_by'
,
'date_created'
,
'hostname_raw'
,
'comment'
,
'created_by'
,
'date_created'
,
'hardware_info'
,
'connectivity'
'hardware_info'
,
'connectivity'
]
]
read_only_fields
=
(
read_only_fields
=
(
'
number'
,
'
vendor'
,
'model'
,
'sn'
,
'cpu_model'
,
'cpu_count'
,
'vendor'
,
'model'
,
'sn'
,
'cpu_model'
,
'cpu_count'
,
'cpu_cores'
,
'cpu_vcpus'
,
'memory'
,
'disk_total'
,
'disk_info'
,
'cpu_cores'
,
'cpu_vcpus'
,
'memory'
,
'disk_total'
,
'disk_info'
,
'os'
,
'os_version'
,
'os_arch'
,
'hostname_raw'
,
'os'
,
'os_version'
,
'os_arch'
,
'hostname_raw'
,
'created_by'
,
'date_created'
,
'created_by'
,
'date_created'
,
...
@@ -43,7 +52,6 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer, OrgResou
...
@@ -43,7 +52,6 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer, OrgResou
'hardware_info'
:
{
'label'
:
_
(
'Hardware info'
)},
'hardware_info'
:
{
'label'
:
_
(
'Hardware info'
)},
'connectivity'
:
{
'label'
:
_
(
'Connectivity'
)},
'connectivity'
:
{
'label'
:
_
(
'Connectivity'
)},
'org_name'
:
{
'label'
:
_
(
'Org name'
)}
'org_name'
:
{
'label'
:
_
(
'Org name'
)}
}
}
@classmethod
@classmethod
...
@@ -53,18 +61,64 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer, OrgResou
...
@@ -53,18 +61,64 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer, OrgResou
.
select_related
(
'admin_user'
)
.
select_related
(
'admin_user'
)
return
queryset
return
queryset
def
get_field_names
(
self
,
declared_fields
,
info
):
@staticmethod
fields
=
super
()
.
get_field_names
(
declared_fields
,
info
)
def
validate_protocols
(
attr
):
fields
.
extend
([
protocols_name
=
[
i
.
get
(
"name"
,
"ssh"
)
for
i
in
attr
]
'hardware_info'
,
'connectivity'
,
'org_name'
errors
=
[{}
for
i
in
protocols_name
]
])
for
i
,
name
in
enumerate
(
protocols_name
):
return
fields
if
name
in
protocols_name
[:
i
]:
errors
[
i
]
=
{
"name"
:
_
(
"Protocol duplicate: {}"
)
.
format
(
name
)}
if
any
(
errors
):
raise
ValidationError
(
errors
)
return
attr
def
create
(
self
,
validated_data
):
protocols_data
=
validated_data
.
pop
(
"protocols"
)
# 兼容老的api
protocol
=
validated_data
.
get
(
"protocol"
)
port
=
validated_data
.
get
(
"port"
)
if
not
protocols_data
and
protocol
and
port
:
protocols_data
=
[{
"name"
:
protocol
,
"port"
:
port
}]
if
not
protocol
and
not
port
and
protocols_data
:
validated_data
[
"protocol"
]
=
protocols_data
[
0
][
"name"
]
validated_data
[
"port"
]
=
protocols_data
[
0
][
"port"
]
protocols_serializer
=
ProtocolSerializer
(
data
=
protocols_data
,
many
=
True
)
protocols_serializer
.
is_valid
(
raise_exception
=
True
)
protocols
=
protocols_serializer
.
save
()
instance
=
super
()
.
create
(
validated_data
)
instance
.
protocols
.
set
(
protocols
)
return
instance
def
update
(
self
,
instance
,
validated_data
):
protocols_data
=
validated_data
.
pop
(
"protocols"
)
# 兼容老的api
protocol
=
validated_data
.
get
(
"protocol"
)
port
=
validated_data
.
get
(
"port"
)
if
not
protocols_data
and
protocol
and
port
:
protocols_data
=
[{
"name"
:
protocol
,
"port"
:
port
}]
if
not
protocol
and
not
port
and
protocols_data
:
validated_data
[
"protocol"
]
=
protocols_data
[
0
][
"name"
]
validated_data
[
"port"
]
=
protocols_data
[
0
][
"port"
]
protocols_serializer
=
ProtocolSerializer
(
data
=
protocols_data
,
many
=
True
)
protocols_serializer
.
is_valid
(
raise_exception
=
True
)
protocols
=
protocols_serializer
.
save
()
instance
=
super
()
.
update
(
instance
,
validated_data
)
instance
.
protocols
.
all
()
.
delete
()
instance
.
protocols
.
set
(
protocols
)
return
instance
class
AssetAsNodeSerializer
(
serializers
.
ModelSerializer
):
class
AssetAsNodeSerializer
(
serializers
.
ModelSerializer
):
class
Meta
:
class
Meta
:
model
=
Asset
model
=
Asset
fields
=
[
'id'
,
'hostname'
,
'ip'
,
'p
ort'
,
'platform'
,
'protocol
'
]
fields
=
[
'id'
,
'hostname'
,
'ip'
,
'p
latform'
,
'protocols
'
]
class
AssetGrantedSerializer
(
serializers
.
ModelSerializer
):
class
AssetGrantedSerializer
(
serializers
.
ModelSerializer
):
...
@@ -78,9 +132,9 @@ class AssetGrantedSerializer(serializers.ModelSerializer):
...
@@ -78,9 +132,9 @@ class AssetGrantedSerializer(serializers.ModelSerializer):
class
Meta
:
class
Meta
:
model
=
Asset
model
=
Asset
fields
=
(
fields
=
(
"id"
,
"hostname"
,
"ip"
,
"
port"
,
"
system_users_granted"
,
"id"
,
"hostname"
,
"ip"
,
"system_users_granted"
,
"is_active"
,
"system_users_join"
,
"os"
,
'domain'
,
"is_active"
,
"system_users_join"
,
"os"
,
'domain'
,
"platform"
,
"comment"
,
"protocol"
,
"org_id"
,
"org_name"
,
"platform"
,
"comment"
,
"protocol
s
"
,
"org_id"
,
"org_name"
,
)
)
@staticmethod
@staticmethod
...
...
apps/assets/signals_handler.py
View file @
a5b874e2
...
@@ -5,6 +5,7 @@ from django.db.models.signals import post_save, m2m_changed, post_delete
...
@@ -5,6 +5,7 @@ from django.db.models.signals import post_save, m2m_changed, post_delete
from
django.dispatch
import
receiver
from
django.dispatch
import
receiver
from
common.utils
import
get_logger
from
common.utils
import
get_logger
from
common.decorator
import
on_transaction_commit
from
.models
import
Asset
,
SystemUser
,
Node
,
AuthBook
from
.models
import
Asset
,
SystemUser
,
Node
,
AuthBook
from
.tasks
import
(
from
.tasks
import
(
update_assets_hardware_info_util
,
update_assets_hardware_info_util
,
...
@@ -32,9 +33,12 @@ def set_asset_root_node(asset):
...
@@ -32,9 +33,12 @@ def set_asset_root_node(asset):
@receiver
(
post_save
,
sender
=
Asset
,
dispatch_uid
=
"my_unique_identifier"
)
@receiver
(
post_save
,
sender
=
Asset
,
dispatch_uid
=
"my_unique_identifier"
)
@on_transaction_commit
def
on_asset_created_or_update
(
sender
,
instance
=
None
,
created
=
False
,
**
kwargs
):
def
on_asset_created_or_update
(
sender
,
instance
=
None
,
created
=
False
,
**
kwargs
):
if
created
:
if
created
:
logger
.
info
(
"Asset `{}` create signal received"
.
format
(
instance
))
logger
.
info
(
"Asset `{}` create signal received"
.
format
(
instance
))
# 获取资产硬件信息
update_asset_hardware_info_on_created
(
instance
)
update_asset_hardware_info_on_created
(
instance
)
test_asset_conn_on_created
(
instance
)
test_asset_conn_on_created
(
instance
)
...
...
apps/assets/templates/assets/asset_create.html
View file @
a5b874e2
...
@@ -16,12 +16,24 @@
...
@@ -16,12 +16,24 @@
<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.platform layout="horizontal" %}
{% bootstrap_field form.platform 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" %}
<div
class=
"hr-line-dashed"
></div>
<h3>
{% trans 'Protocols' %}
</h3>
<div
class=
"protocols"
>
{% for fm in formset.forms %}
<div
class=
"form-group"
>
<div
class=
"col-md-2 col-md-offset-2"
style=
"text-align: right"
>
{{ fm.name }}
</div>
<div
class=
"col-md-6"
>
{{ fm.port }}
</div>
<div
class=
"col-md-1"
style=
"padding: 6px 0"
>
<a
class=
"btn btn-danger btn-xs btn-protocol btn-del"
><span
class=
"fa fa-minus"
></span>
</a>
<a
class=
"btn btn-primary btn-xs btn-protocol btn-add"
style=
"display: none"
><span
class=
"fa fa-plus"
></span></a>
</div>
</div>
{% endfor %}
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"hr-line-dashed"
></div>
<h3>
{% trans 'Auth' %}
</h3>
<h3>
{% trans 'Auth' %}
</h3>
{% bootstrap_field form.admin_user layout="horizontal" %}
{% bootstrap_field form.admin_user layout="horizontal" %}
...
@@ -55,6 +67,8 @@
...
@@ -55,6 +67,8 @@
{% endif %}
{% endif %}
</div>
</div>
</div>
</div>
{% block extra %}
{% endblock %}
<div
class=
"hr-line-dashed"
></div>
<div
class=
"hr-line-dashed"
></div>
<h3>
{% trans 'Other' %}
</h3>
<h3>
{% trans 'Other' %}
</h3>
...
@@ -73,11 +87,25 @@
...
@@ -73,11 +87,25 @@
{% block custom_foot_js %}
{% block custom_foot_js %}
<script>
<script>
var
instanceId
=
"{{ object.id }}"
;
var
protocolLen
=
0
;
function
format
(
item
)
{
function
format
(
item
)
{
var
group
=
item
.
element
.
parentElement
.
label
;
var
group
=
item
.
element
.
parentElement
.
label
;
return
group
+
':'
+
item
.
text
;
return
group
+
':'
+
item
.
text
;
}
}
function
protocolBtnShow
()
{
$
(
".btn-protocol.btn-add"
).
hide
();
$
(
".btn-protocol.btn-add:last"
).
show
();
var
btnDel
=
$
(
".btn-protocol.btn-del"
);
if
(
btnDel
.
length
===
1
)
{
btnDel
.
addClass
(
"disabled"
)
}
else
{
btnDel
.
removeClass
(
"disabled"
)
}
}
$
(
document
).
ready
(
function
()
{
$
(
document
).
ready
(
function
()
{
$
(
'.select2'
).
select2
({
$
(
'.select2'
).
select2
({
allowClear
:
true
allowClear
:
true
...
@@ -89,20 +117,130 @@ $(document).ready(function () {
...
@@ -89,20 +117,130 @@ $(document).ready(function () {
$
(
'#id_nodes.select2'
).
select2
({
$
(
'#id_nodes.select2'
).
select2
({
closeOnSelect
:
false
closeOnSelect
:
false
});
});
$
(
"#id_protocol"
).
change
(
function
(){
protocolBtnShow
()
var
protocol
=
$
(
"#id_protocol option:selected"
).
text
();
})
var
port
=
22
;
.
on
(
"change"
,
"#id_platform"
,
function
()
{
if
(
protocol
===
'rdp'
){
if
(
instanceId
!==
""
)
{
port
=
3389
;
return
}
}
else
if
(
protocol
===
'telnet (beta)'
){
var
platform
=
$
(
this
).
val
();
port
=
23
;
var
protocolRef
=
$
(
".protocols"
).
find
(
"select"
).
first
()
var
protocol
=
protocolRef
.
val
();
var
protocolShould
=
""
;
if
(
platform
.
startsWith
(
"Windows"
)){
protocolShould
=
"rdp"
}
else
{
protocolShould
=
"ssh"
}
if
(
protocol
!==
protocolShould
)
{
protocolRef
.
val
(
protocolShould
);
protocolRef
.
trigger
(
"change"
)
}
})
.
on
(
"click"
,
".btn-protocol.btn-del"
,
function
()
{
$
(
this
).
parent
().
parent
().
remove
();
protocolBtnShow
()
})
.
on
(
"click"
,
".btn-protocol.btn-add"
,
function
()
{
var
protocol
=
""
;
var
protocolsRef
=
$
(
".protocols"
);
var
firstProtocolForm
=
protocolsRef
.
children
().
first
();
var
newProtocolForm
=
firstProtocolForm
.
clone
();
var
protocolChoices
=
$
.
map
(
$
(
firstProtocolForm
.
find
(
'select option'
)),
function
(
option
)
{
return
option
.
value
});
var
protocolsSet
=
$
.
map
(
protocolsRef
.
find
(
'select option:selected'
),
function
(
option
)
{
return
option
.
value
});
for
(
var
i
=
0
;
i
<
protocolChoices
.
length
;
i
++
)
{
var
p
=
protocolChoices
[
i
];
if
(
protocolsSet
.
indexOf
(
p
)
===
-
1
)
{
protocol
=
p
;
break
}
}
else
if
(
protocol
===
'vnc'
){
}
if
(
protocol
===
""
)
{
return
}
if
(
protocolLen
===
0
)
{
protocolLen
=
protocolsRef
.
length
;
}
var
selectName
=
"form-"
+
protocolLen
+
"-name"
;
var
selectId
=
"id_"
+
selectName
;
var
portName
=
"form-"
+
protocolLen
+
"-port"
;
var
portId
=
"id_"
+
portName
;
newProtocolForm
.
find
(
"select"
).
prop
(
"name"
,
selectName
).
prop
(
"id"
,
selectId
);
newProtocolForm
.
find
(
"input"
).
prop
(
"name"
,
portName
).
prop
(
"id"
,
portId
);
newProtocolForm
.
find
(
"option[value='"
+
protocol
+
"']"
).
attr
(
"selected"
,
true
);
protocolsRef
.
append
(
newProtocolForm
);
protocolLen
+=
1
;
$
(
"#"
+
selectId
).
trigger
(
"change"
);
protocolBtnShow
()
})
.
on
(
"change"
,
".protocol-name"
,
function
()
{
var
name
=
$
(
this
).
val
();
var
port
=
22
;
switch
(
name
)
{
case
"ssh"
:
port
=
22
;
break
;
case
"rdp"
:
port
=
3389
;
break
;
case
"telnet"
:
port
=
21
;
break
;
case
"vnc"
:
port
=
5901
;
port
=
5901
;
}
break
;
$
(
"#id_port"
).
val
(
port
);
default
:
});
port
=
22
;
break
}
$
(
this
).
parent
().
parent
().
find
(
".protocol-port"
).
val
(
port
);
})
})
</script>
</script>
{% block form_submit %}
<script>
$
(
document
).
ready
(
function
()
{
})
.
on
(
"submit"
,
"form"
,
function
(
evt
)
{
evt
.
preventDefault
();
var
the_url
=
'{% url '
api
-
assets
:
asset
-
list
' %}'
;
var
redirect_to
=
'{% url "assets:asset-list" %}'
;
var
form
=
$
(
"form"
);
var
protocols
=
{};
var
data
=
form
.
serializeObject
();
$
.
each
(
data
,
function
(
k
,
v
)
{
if
(
k
.
startsWith
(
"form"
)){
delete
data
[
k
];
var
_k
=
k
.
split
(
"-"
);
var
formName
=
_k
.
slice
(
0
,
2
).
join
(
"-"
);
var
key
=
_k
[
_k
.
length
-
1
];
if
(
!
protocols
[
formName
])
{
protocols
[
formName
]
=
{}
}
protocols
[
formName
][
key
]
=
v
}
});
protocols
=
$
.
map
(
protocols
,
function
(
v
)
{
return
v
});
data
[
"protocols"
]
=
protocols
;
if
(
typeof
data
[
"nodes"
]
==
"string"
)
{
data
[
"nodes"
]
=
[
data
[
"nodes"
]]
}
var
props
=
{
url
:
the_url
,
data
:
data
,
method
:
"POST"
,
form
:
form
,
redirect_to
:
redirect_to
};
formSubmit
(
props
);
})
</script>
{% endblock %}
{% endblock %}
{% endblock %}
\ No newline at end of file
apps/assets/templates/assets/asset_update.html
View file @
a5b874e2
{% extends '_base_create_update.html' %}
{% extends 'assets/asset_create.html' %}
{% load static %}
{% load bootstrap3 %}
{% load bootstrap3 %}
{% load i18n %}
{% load i18n %}
{% load asset_tags %}
{% load common_tags %}
{% block custom_head_css_js_create %}
<link
href=
"{% static "
css
/
plugins
/
inputTags
.
css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static "
js
/
plugins
/
inputTags
.
jquery
.
min
.
js
"
%}"
></script>
{% endblock %}
{% block form %}
<form
action=
""
method=
"post"
class=
"form-horizontal"
>
{% if form.non_field_errors %}
<div
class=
"alert alert-danger"
>
{{ form.non_field_errors }}
</div>
{% endif %}
{% csrf_token %}
<h3>
{% trans 'Basic' %}
</h3>
{% bootstrap_field form.hostname layout="horizontal" %}
{% bootstrap_field form.ip layout="horizontal" %}
{% bootstrap_field form.protocol layout="horizontal" %}
{% bootstrap_field form.port layout="horizontal" %}
{% bootstrap_field form.platform layout="horizontal" %}
{% bootstrap_field form.public_ip layout="horizontal" %}
{% bootstrap_field form.domain layout="horizontal" %}
<div
class=
"hr-line-dashed"
></div>
<h3>
{% trans 'Auth' %}
</h3>
{% bootstrap_field form.admin_user layout="horizontal" %}
<div
class=
"hr-line-dashed"
></div>
<h3>
{% trans 'Node' %}
</h3>
{% bootstrap_field form.nodes layout="horizontal" %}
<div
class=
"hr-line-dashed"
></div>
<h3>
{% trans 'Labels' %}
</h3>
<div
class=
"form-group"
>
<label
for=
"{{ form.labels.id_for_label }}"
class=
"col-md-2 control-label"
>
{% trans 'Label' %}
</label>
<div
class=
"col-md-9"
>
<select
name=
"labels"
class=
"select2 labels"
data-placeholder=
"{% trans 'Label' %}"
style=
"width: 100%"
multiple=
""
tabindex=
"4"
id=
"{{ form.labels.id_for_label }}"
>
{% for name, labels in form.labels.field.queryset|group_labels %}
<optgroup
label=
"{{ name }}"
>
{% for label in labels %}
{% if label in form.labels.initial %}
<option
value=
"{{ label.id }}"
selected
>
{{ label.value }}
</option>
{% else %}
<option
value=
"{{ label.id }}"
>
{{ label.value }}
</option>
{% endif %}
{% endfor %}
</optgroup>
{% endfor %}
</select>
</div>
</div>
{% block extra %}
<div
class=
"hr-line-dashed"
></div>
<div
class=
"hr-line-dashed"
></div>
<h3>
{% trans 'Configuration' %}
</h3>
<h3>
{% trans 'Configuration' %}
</h3>
{% bootstrap_field form.number layout="horizontal" %}
{% bootstrap_field form.number layout="horizontal" %}
<div
class=
"hr-line-dashed"
></div>
<h3>
{% trans 'Other' %}
</h3>
{% bootstrap_field form.comment layout="horizontal" %}
{% bootstrap_field form.is_active layout="horizontal" %}
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
<button
class=
"btn btn-white"
type=
"reset"
>
{% trans 'Reset' %}
</button>
<button
id=
"submit_button"
class=
"btn btn-primary"
type=
"submit"
>
{% trans 'Submit' %}
</button>
</div>
</div>
</form>
{% endblock %}
{% endblock %}
{% block custom_foot_js %}
{% block form_submit %}
<script>
<script>
function
format
(
item
)
{
var
group
=
item
.
element
.
parentElement
.
label
;
return
group
+
':'
+
item
.
text
;
}
$
(
document
).
ready
(
function
()
{
$
(
document
).
ready
(
function
()
{
$
(
'.select2'
).
select2
({
allowClear
:
true
});
$
(
".labels"
).
select2
({
allowClear
:
true
,
templateSelection
:
format
});
})
})
</script>
.
on
(
"submit"
,
"form"
,
function
(
evt
)
{
evt
.
preventDefault
();
var
the_url
=
'{% url '
api
-
assets
:
asset
-
detail
' pk=object.id %}'
;
var
redirect_to
=
'{% url "assets:asset-list" %}'
;
var
form
=
$
(
"form"
);
var
protocols
=
{};
var
data
=
form
.
serializeObject
();
$
.
each
(
data
,
function
(
k
,
v
)
{
if
(
k
.
startsWith
(
"form"
)){
delete
data
[
k
];
var
_k
=
k
.
split
(
"-"
);
var
formName
=
_k
.
slice
(
0
,
2
).
join
(
"-"
);
var
key
=
_k
[
_k
.
length
-
1
];
if
(
!
protocols
[
formName
])
{
protocols
[
formName
]
=
{}
}
protocols
[
formName
][
key
]
=
v
}
});
protocols
=
$
.
map
(
protocols
,
function
(
v
)
{
return
v
});
data
[
"protocols"
]
=
protocols
;
if
(
typeof
data
[
"nodes"
]
==
"string"
)
{
data
[
"nodes"
]
=
[
data
[
"nodes"
]]
}
var
props
=
{
url
:
the_url
,
data
:
data
,
method
:
"PUT"
,
form
:
form
,
redirect_to
:
redirect_to
};
formSubmit
(
props
);
});
</script>
{% endblock %}
{% endblock %}
\ No newline at end of file
apps/assets/views/asset.py
View file @
a5b874e2
...
@@ -23,6 +23,7 @@ from django.utils import timezone
...
@@ -23,6 +23,7 @@ from django.utils import timezone
from
django.contrib.auth.mixins
import
LoginRequiredMixin
from
django.contrib.auth.mixins
import
LoginRequiredMixin
from
django.shortcuts
import
redirect
from
django.shortcuts
import
redirect
from
django.contrib.messages.views
import
SuccessMessageMixin
from
django.contrib.messages.views
import
SuccessMessageMixin
from
django.forms.formsets
import
formset_factory
from
common.mixins
import
JSONResponseMixin
from
common.mixins
import
JSONResponseMixin
from
common.utils
import
get_object_or_none
,
get_logger
from
common.utils
import
get_object_or_none
,
get_logger
...
@@ -30,8 +31,6 @@ from common.permissions import AdminUserRequiredMixin
...
@@ -30,8 +31,6 @@ from common.permissions import AdminUserRequiredMixin
from
common.const
import
(
from
common.const
import
(
create_success_msg
,
update_success_msg
,
KEY_CACHE_RESOURCES_ID
create_success_msg
,
update_success_msg
,
KEY_CACHE_RESOURCES_ID
)
)
from
..const
import
CACHE_KEY_ASSET_BULK_UPDATE_ID_PREFIX
from
orgs.utils
import
current_org
from
..
import
forms
from
..
import
forms
from
..models
import
Asset
,
AdminUser
,
SystemUser
,
Label
,
Node
,
Domain
from
..models
import
Asset
,
AdminUser
,
SystemUser
,
Label
,
Node
,
Domain
...
@@ -101,10 +100,30 @@ class AssetCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView):
...
@@ -101,10 +100,30 @@ class AssetCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView):
form
[
"nodes"
]
.
initial
=
node
form
[
"nodes"
]
.
initial
=
node
return
form
return
form
def
get_protocol_formset
(
self
):
ProtocolFormset
=
formset_factory
(
forms
.
ProtocolForm
,
extra
=
0
,
min_num
=
1
,
max_num
=
5
)
if
self
.
request
.
method
==
"POST"
:
formset
=
ProtocolFormset
(
self
.
request
.
POST
)
else
:
formset
=
ProtocolFormset
()
return
formset
def
form_valid
(
self
,
form
):
formset
=
self
.
get_protocol_formset
()
valid
=
formset
.
is_valid
()
if
not
valid
:
return
self
.
form_invalid
(
form
)
protocols
=
formset
.
save
()
instance
=
super
()
.
form_valid
(
form
)
instance
.
protocols
.
set
(
protocols
)
return
instance
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
formset
=
self
.
get_protocol_formset
()
context
=
{
context
=
{
'app'
:
_
(
'Assets'
),
'app'
:
_
(
'Assets'
),
'action'
:
_
(
'Create asset'
),
'action'
:
_
(
'Create asset'
),
'formset'
:
formset
,
}
}
kwargs
.
update
(
context
)
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
return
super
()
.
get_context_data
(
**
kwargs
)
...
@@ -159,10 +178,21 @@ class AssetUpdateView(AdminUserRequiredMixin, SuccessMessageMixin, UpdateView):
...
@@ -159,10 +178,21 @@ class AssetUpdateView(AdminUserRequiredMixin, SuccessMessageMixin, UpdateView):
template_name
=
'assets/asset_update.html'
template_name
=
'assets/asset_update.html'
success_url
=
reverse_lazy
(
'assets:asset-list'
)
success_url
=
reverse_lazy
(
'assets:asset-list'
)
def
get_protocol_formset
(
self
):
ProtocolFormset
=
formset_factory
(
forms
.
ProtocolForm
,
extra
=
0
,
min_num
=
1
,
max_num
=
5
)
if
self
.
request
.
method
==
"POST"
:
formset
=
ProtocolFormset
(
self
.
request
.
POST
)
else
:
initial_data
=
[{
"name"
:
p
.
name
,
"port"
:
p
.
port
}
for
p
in
self
.
object
.
protocols
.
all
()]
formset
=
ProtocolFormset
(
initial
=
initial_data
)
return
formset
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
formset
=
self
.
get_protocol_formset
()
context
=
{
context
=
{
'app'
:
_
(
'Assets'
),
'app'
:
_
(
'Assets'
),
'action'
:
_
(
'Update asset'
),
'action'
:
_
(
'Update asset'
),
'formset'
:
formset
,
}
}
kwargs
.
update
(
context
)
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
return
super
()
.
get_context_data
(
**
kwargs
)
...
...
apps/common/decorator.py
0 → 100644
View file @
a5b874e2
# -*- coding: utf-8 -*-
#
from
django.db
import
transaction
def
on_transaction_commit
(
func
):
"""
如果不调用on_commit, 对象创建时添加多对多字段值失败
"""
def
inner
(
*
args
,
**
kwargs
):
transaction
.
on_commit
(
lambda
:
func
(
*
args
,
**
kwargs
))
return
inner
apps/common/mixins.py
View file @
a5b874e2
...
@@ -5,6 +5,7 @@ from django.http import JsonResponse
...
@@ -5,6 +5,7 @@ from django.http import JsonResponse
from
django.utils
import
timezone
from
django.utils
import
timezone
from
django.core.cache
import
cache
from
django.core.cache
import
cache
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.contrib
import
messages
from
rest_framework.utils
import
html
from
rest_framework.utils
import
html
from
rest_framework.settings
import
api_settings
from
rest_framework.settings
import
api_settings
from
rest_framework.exceptions
import
ValidationError
from
rest_framework.exceptions
import
ValidationError
...
@@ -203,3 +204,26 @@ class DatetimeSearchMixin:
...
@@ -203,3 +204,26 @@ class DatetimeSearchMixin:
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
self
.
get_date_range
()
self
.
get_date_range
()
return
super
()
.
get
(
request
,
*
args
,
**
kwargs
)
return
super
()
.
get
(
request
,
*
args
,
**
kwargs
)
class
ApiMessageMixin
:
success_message
=
_
(
"
%(name)
s was
%(action)
s successfully"
)
_action_map
=
{
"create"
:
_
(
"create"
),
"update"
:
_
(
"update"
)}
def
get_success_message
(
self
,
cleaned_data
):
data
=
{
k
:
v
for
k
,
v
in
cleaned_data
.
items
()}
action
=
getattr
(
self
,
"action"
,
"create"
)
data
[
"action"
]
=
self
.
_action_map
.
get
(
action
)
message
=
self
.
success_message
%
data
return
message
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
resp
=
super
()
.
dispatch
(
request
,
*
args
,
**
kwargs
)
if
request
.
method
.
lower
()
in
(
"get"
,
"delete"
):
return
resp
if
resp
.
status_code
>=
400
:
return
resp
message
=
self
.
get_success_message
(
resp
.
data
)
if
message
:
messages
.
success
(
request
,
message
)
return
resp
apps/common/validators.py
View file @
a5b874e2
...
@@ -3,5 +3,22 @@
...
@@ -3,5 +3,22 @@
from
django.core.validators
import
RegexValidator
from
django.core.validators
import
RegexValidator
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.translation
import
ugettext_lazy
as
_
from
rest_framework.validators
import
(
UniqueTogetherValidator
,
ValidationError
)
alphanumeric
=
RegexValidator
(
r'^[0-9a-zA-Z_@\-\.]*$'
,
_
(
'Special char not allowed'
))
\ No newline at end of file
alphanumeric
=
RegexValidator
(
r'^[0-9a-zA-Z_@\-\.]*$'
,
_
(
'Special char not allowed'
))
class
ProjectUniqueValidator
(
UniqueTogetherValidator
):
def
__call__
(
self
,
attrs
):
try
:
super
()
.
__call__
(
attrs
)
except
ValidationError
as
e
:
errors
=
{}
for
field
in
self
.
fields
:
if
field
==
"org_id"
:
continue
errors
[
field
]
=
_
(
'This field must be unique.'
)
raise
ValidationError
(
errors
)
apps/jumpserver/conf.py
View file @
a5b874e2
...
@@ -274,7 +274,10 @@ class Config(dict):
...
@@ -274,7 +274,10 @@ class Config(dict):
return
v
return
v
tp
=
type
(
default_value
)
tp
=
type
(
default_value
)
try
:
try
:
v
=
tp
(
v
)
if
tp
in
[
list
,
dict
]:
v
=
json
.
loads
(
v
)
else
:
v
=
tp
(
v
)
except
Exception
:
except
Exception
:
pass
pass
return
v
return
v
...
...
apps/locale/zh/LC_MESSAGES/django.mo
View file @
a5b874e2
No preview for this file type
apps/locale/zh/LC_MESSAGES/django.po
View file @
a5b874e2
...
@@ -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: 2019-05-2
1 21:0
9+0800\n"
"POT-Creation-Date: 2019-05-2
4 10:2
9+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"
...
@@ -76,7 +76,7 @@ msgstr "运行参数"
...
@@ -76,7 +76,7 @@ msgstr "运行参数"
#: applications/templates/applications/remote_app_list.html:22
#: applications/templates/applications/remote_app_list.html:22
#: applications/templates/applications/user_remote_app_list.html:18
#: applications/templates/applications/user_remote_app_list.html:18
#: assets/forms/domain.py:15 assets/forms/label.py:13
#: assets/forms/domain.py:15 assets/forms/label.py:13
#: assets/models/asset.py:2
79
assets/models/authbook.py:27
#: assets/models/asset.py:2
96
assets/models/authbook.py:27
#: assets/serializers/admin_user.py:23 assets/serializers/system_user.py:28
#: assets/serializers/admin_user.py:23 assets/serializers/system_user.py:28
#: assets/templates/assets/admin_user_list.html:49
#: assets/templates/assets/admin_user_list.html:49
#: assets/templates/assets/domain_detail.html:60
#: assets/templates/assets/domain_detail.html:60
...
@@ -133,10 +133,10 @@ msgstr "系统用户"
...
@@ -133,10 +133,10 @@ msgstr "系统用户"
#: applications/templates/applications/remote_app_list.html:20
#: applications/templates/applications/remote_app_list.html:20
#: applications/templates/applications/user_remote_app_list.html:16
#: applications/templates/applications/user_remote_app_list.html:16
#: assets/forms/domain.py:73 assets/forms/user.py:84 assets/forms/user.py:146
#: assets/forms/domain.py:73 assets/forms/user.py:84 assets/forms/user.py:146
#: assets/models/
base.py:26 assets/models/cluster.py:18
#: assets/models/
asset.py:66 assets/models/base.py:26
#: assets/models/c
md_filter.py:20 assets/models/domain
.py:20
#: assets/models/c
luster.py:18 assets/models/cmd_filter
.py:20
#: assets/models/
group.py:20 assets/models/label.py:18
#: assets/models/
domain.py:20 assets/models/group.py:20
#: assets/templates/assets/admin_user_detail.html:56
#: assets/
models/label.py:18 assets/
templates/assets/admin_user_detail.html:56
#: assets/templates/assets/admin_user_list.html:47
#: assets/templates/assets/admin_user_list.html:47
#: assets/templates/assets/cmd_filter_detail.html:61
#: assets/templates/assets/cmd_filter_detail.html:61
#: assets/templates/assets/cmd_filter_list.html:24
#: assets/templates/assets/cmd_filter_list.html:24
...
@@ -204,7 +204,7 @@ msgstr "参数"
...
@@ -204,7 +204,7 @@ msgstr "参数"
#: applications/models/remote_app.py:43
#: applications/models/remote_app.py:43
#: applications/templates/applications/remote_app_detail.html:77
#: applications/templates/applications/remote_app_detail.html:77
#: assets/models/asset.py:1
09
assets/models/base.py:34
#: assets/models/asset.py:1
26
assets/models/base.py:34
#: assets/models/cluster.py:28 assets/models/cmd_filter.py:25
#: assets/models/cluster.py:28 assets/models/cmd_filter.py:25
#: assets/models/cmd_filter.py:58 assets/models/group.py:21
#: assets/models/cmd_filter.py:58 assets/models/group.py:21
#: assets/templates/assets/admin_user_detail.html:68
#: assets/templates/assets/admin_user_detail.html:68
...
@@ -226,7 +226,7 @@ msgstr "创建者"
...
@@ -226,7 +226,7 @@ msgstr "创建者"
#: applications/models/remote_app.py:46
#: applications/models/remote_app.py:46
#: applications/templates/applications/remote_app_detail.html:73
#: applications/templates/applications/remote_app_detail.html:73
#: assets/models/asset.py:1
10
assets/models/cluster.py:26
#: assets/models/asset.py:1
27
assets/models/cluster.py:26
#: assets/models/domain.py:23 assets/models/group.py:22
#: assets/models/domain.py:23 assets/models/group.py:22
#: assets/models/label.py:25 assets/serializers/admin_user.py:37
#: assets/models/label.py:25 assets/serializers/admin_user.py:37
#: assets/templates/assets/admin_user_detail.html:64
#: assets/templates/assets/admin_user_detail.html:64
...
@@ -252,7 +252,7 @@ msgstr "创建日期"
...
@@ -252,7 +252,7 @@ msgstr "创建日期"
#: applications/templates/applications/remote_app_detail.html:81
#: applications/templates/applications/remote_app_detail.html:81
#: applications/templates/applications/remote_app_list.html:24
#: applications/templates/applications/remote_app_list.html:24
#: applications/templates/applications/user_remote_app_list.html:20
#: applications/templates/applications/user_remote_app_list.html:20
#: assets/models/asset.py:1
11
assets/models/base.py:31
#: assets/models/asset.py:1
28
assets/models/base.py:31
#: assets/models/cluster.py:29 assets/models/cmd_filter.py:22
#: assets/models/cluster.py:29 assets/models/cmd_filter.py:22
#: assets/models/cmd_filter.py:55 assets/models/domain.py:21
#: assets/models/cmd_filter.py:55 assets/models/domain.py:21
#: assets/models/domain.py:53 assets/models/group.py:23
#: assets/models/domain.py:53 assets/models/group.py:23
...
@@ -306,7 +306,7 @@ msgstr "远程应用"
...
@@ -306,7 +306,7 @@ msgstr "远程应用"
#: assets/templates/assets/_system_user.html:75
#: assets/templates/assets/_system_user.html:75
#: 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:
67
#: assets/templates/assets/asset_create.html:
79
#: assets/templates/assets/asset_update.html:71
#: assets/templates/assets/asset_update.html:71
#: assets/templates/assets/cmd_filter_create_update.html:15
#: assets/templates/assets/cmd_filter_create_update.html:15
#: assets/templates/assets/cmd_filter_rule_create_update.html:40
#: assets/templates/assets/cmd_filter_rule_create_update.html:40
...
@@ -342,7 +342,7 @@ msgstr "重置"
...
@@ -342,7 +342,7 @@ msgstr "重置"
#: assets/templates/assets/_system_user.html:76
#: assets/templates/assets/_system_user.html:76
#: 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:
68
#: assets/templates/assets/asset_create.html:
80
#: assets/templates/assets/asset_list.html:125
#: assets/templates/assets/asset_list.html:125
#: assets/templates/assets/asset_update.html:72
#: assets/templates/assets/asset_update.html:72
#: assets/templates/assets/cmd_filter_create_update.html:16
#: assets/templates/assets/cmd_filter_create_update.html:16
...
@@ -556,9 +556,9 @@ msgstr "连接"
...
@@ -556,9 +556,9 @@ msgstr "连接"
#: assets/templates/assets/system_user_detail.html:22
#: assets/templates/assets/system_user_detail.html:22
#: assets/views/admin_user.py:29 assets/views/admin_user.py:47
#: assets/views/admin_user.py:29 assets/views/admin_user.py:47
#: assets/views/admin_user.py:63 assets/views/admin_user.py:78
#: assets/views/admin_user.py:63 assets/views/admin_user.py:78
#: assets/views/admin_user.py:102 assets/views/asset.py:5
3
#: assets/views/admin_user.py:102 assets/views/asset.py:5
2
#: assets/views/asset.py:6
9 assets/views/asset.py:106 assets/views/asset.py:147
#: assets/views/asset.py:6
8 assets/views/asset.py:124 assets/views/asset.py:166
#: assets/views/asset.py:1
64 assets/views/asset.py:188
#: assets/views/asset.py:1
83 assets/views/asset.py:207
#: assets/views/cmd_filter.py:30 assets/views/cmd_filter.py:46
#: assets/views/cmd_filter.py:30 assets/views/cmd_filter.py:46
#: assets/views/cmd_filter.py:62 assets/views/cmd_filter.py:78
#: assets/views/cmd_filter.py:62 assets/views/cmd_filter.py:78
#: assets/views/cmd_filter.py:97 assets/views/cmd_filter.py:130
#: assets/views/cmd_filter.py:97 assets/views/cmd_filter.py:130
...
@@ -589,7 +589,12 @@ msgstr "远程应用详情"
...
@@ -589,7 +589,12 @@ msgstr "远程应用详情"
msgid "My RemoteApp"
msgid "My RemoteApp"
msgstr "我的远程应用"
msgstr "我的远程应用"
#: assets/api/asset.py:126
#: assets/api/asset.py:50
#, python-format
msgid "%(hostname)s was %(action)s successfully"
msgstr "%(hostname)s %(action)s成功"
#: assets/api/asset.py:127
msgid "Please select assets that need to be updated"
msgid "Please select assets that need to be updated"
msgstr "请选择需要更新的资产"
msgstr "请选择需要更新的资产"
...
@@ -605,7 +610,7 @@ msgstr "更新节点资产硬件信息: {}"
...
@@ -605,7 +610,7 @@ msgstr "更新节点资产硬件信息: {}"
msgid "Test if the assets under the node are connectable: {}"
msgid "Test if the assets under the node are connectable: {}"
msgstr "测试节点下资产是否可连接: {}"
msgstr "测试节点下资产是否可连接: {}"
#: assets/forms/asset.py:
27 assets/models/asset.py:80
assets/models/user.py:133
#: assets/forms/asset.py:
45 assets/models/asset.py:97
assets/models/user.py:133
#: assets/templates/assets/asset_detail.html:194
#: assets/templates/assets/asset_detail.html:194
#: assets/templates/assets/asset_detail.html:202
#: assets/templates/assets/asset_detail.html:202
#: assets/templates/assets/system_user_asset.html:95
#: assets/templates/assets/system_user_asset.html:95
...
@@ -614,7 +619,7 @@ msgstr "测试节点下资产是否可连接: {}"
...
@@ -614,7 +619,7 @@ msgstr "测试节点下资产是否可连接: {}"
msgid "Nodes"
msgid "Nodes"
msgstr "节点管理"
msgstr "节点管理"
#: assets/forms/asset.py:
30 assets/forms/asset.py:66 assets/models/asset.py:84
#: assets/forms/asset.py:
48 assets/forms/asset.py:83 assets/models/asset.py:101
#: assets/models/cluster.py:19 assets/models/user.py:91
#: assets/models/cluster.py:19 assets/models/user.py:91
#: assets/templates/assets/asset_detail.html:80 templates/_nav.html:24
#: assets/templates/assets/asset_detail.html:80 templates/_nav.html:24
#: xpack/plugins/cloud/models.py:124
#: xpack/plugins/cloud/models.py:124
...
@@ -623,9 +628,9 @@ msgstr "节点管理"
...
@@ -623,9 +628,9 @@ msgstr "节点管理"
msgid "Admin user"
msgid "Admin user"
msgstr "管理用户"
msgstr "管理用户"
#: assets/forms/asset.py:
33 assets/forms/asset.py:69 assets/forms/asset.py:109
#: assets/forms/asset.py:
51 assets/forms/asset.py:86 assets/forms/asset.py:125
#: assets/templates/assets/asset_create.html:
36
#: assets/templates/assets/asset_create.html:
48
#: assets/templates/assets/asset_create.html:
38
#: assets/templates/assets/asset_create.html:
50
#: assets/templates/assets/asset_list.html:93
#: assets/templates/assets/asset_list.html:93
#: assets/templates/assets/asset_update.html:41
#: assets/templates/assets/asset_update.html:41
#: assets/templates/assets/asset_update.html:43
#: assets/templates/assets/asset_update.html:43
...
@@ -634,7 +639,7 @@ msgstr "管理用户"
...
@@ -634,7 +639,7 @@ msgstr "管理用户"
msgid "Label"
msgid "Label"
msgstr "标签"
msgstr "标签"
#: assets/forms/asset.py:
37 assets/forms/asset.py:73 assets/models/asset.py:79
#: assets/forms/asset.py:
54 assets/forms/asset.py:89 assets/models/asset.py:96
#: assets/models/domain.py:26 assets/models/domain.py:52
#: assets/models/domain.py:26 assets/models/domain.py:52
#: assets/templates/assets/asset_detail.html:84
#: assets/templates/assets/asset_detail.html:84
#: assets/templates/assets/user_asset_list.html:169
#: assets/templates/assets/user_asset_list.html:169
...
@@ -642,9 +647,9 @@ msgstr "标签"
...
@@ -642,9 +647,9 @@ msgstr "标签"
msgid "Domain"
msgid "Domain"
msgstr "网域"
msgstr "网域"
#: assets/forms/asset.py:
41 assets/forms/asset.py:63 assets/forms/asset.py:77
#: assets/forms/asset.py:
58 assets/forms/asset.py:80 assets/forms/asset.py:93
#: assets/forms/asset.py:1
12
assets/models/node.py:31
#: assets/forms/asset.py:1
28
assets/models/node.py:31
#: assets/templates/assets/asset_create.html:
30
#: assets/templates/assets/asset_create.html:
42
#: assets/templates/assets/asset_update.html:35
#: assets/templates/assets/asset_update.html:35
#: perms/forms/asset_permission.py:49 perms/forms/asset_permission.py:59
#: perms/forms/asset_permission.py:49 perms/forms/asset_permission.py:59
#: perms/models/asset_permission.py:57
#: perms/models/asset_permission.py:57
...
@@ -660,7 +665,7 @@ msgstr "网域"
...
@@ -660,7 +665,7 @@ msgstr "网域"
msgid "Node"
msgid "Node"
msgstr "节点"
msgstr "节点"
#: assets/forms/asset.py:
45 assets/forms/asset.py:81
#: assets/forms/asset.py:
62 assets/forms/asset.py:97
msgid ""
msgid ""
"root or other NOPASSWD sudo privilege user existed in asset,If asset is "
"root or other NOPASSWD sudo privilege user existed in asset,If asset is "
"windows or other set any one, more see admin user left menu"
"windows or other set any one, more see admin user left menu"
...
@@ -668,17 +673,17 @@ msgstr ""
...
@@ -668,17 +673,17 @@ msgstr ""
"root或其他拥有NOPASSWD: ALL权限的用户, 如果是windows或其它硬件可以随意设置一"
"root或其他拥有NOPASSWD: ALL权限的用户, 如果是windows或其它硬件可以随意设置一"
"个, 更多信息查看左侧 `管理用户` 菜单"
"个, 更多信息查看左侧 `管理用户` 菜单"
#: assets/forms/asset.py:
48 assets/forms/asset.py:84
#: assets/forms/asset.py:
65 assets/forms/asset.py:100
msgid "Windows 2016 RDP protocol is different, If is window 2016, set it"
msgid "Windows 2016 RDP protocol is different, If is window 2016, set it"
msgstr "Windows 2016的RDP协议与之前不同,如果是请设置"
msgstr "Windows 2016的RDP协议与之前不同,如果是请设置"
#: assets/forms/asset.py:
49 assets/forms/asset.py:85
#: assets/forms/asset.py:
66 assets/forms/asset.py:101
msgid ""
msgid ""
"If your have some network not connect with each other, you can set domain"
"If your have some network not connect with each other, you can set domain"
msgstr "如果有多个的互相隔离的网络,设置资产属于的网域,使用网域网关跳转登录"
msgstr "如果有多个的互相隔离的网络,设置资产属于的网域,使用网域网关跳转登录"
#: assets/forms/asset.py:
92 assets/forms/asset.py:96 assets/forms/domain.py:17
#: assets/forms/asset.py:
108 assets/forms/asset.py:112
#: assets/forms/label.py:15
#: assets/forms/
domain.py:17 assets/forms/
label.py:15
#: perms/templates/perms/asset_permission_asset.html:88
#: perms/templates/perms/asset_permission_asset.html:88
#: xpack/plugins/change_auth_plan/forms.py:105
#: xpack/plugins/change_auth_plan/forms.py:105
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:84
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:84
...
@@ -794,7 +799,17 @@ msgstr "如果选择手动登录模式,用户名和密码可以不填写"
...
@@ -794,7 +799,17 @@ msgstr "如果选择手动登录模式,用户名和密码可以不填写"
msgid "Use comma split multi command, ex: /bin/whoami,/bin/ifconfig"
msgid "Use comma split multi command, ex: /bin/whoami,/bin/ifconfig"
msgstr "使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig"
msgstr "使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig"
#: assets/models/asset.py:74 assets/models/domain.py:49
#: assets/models/asset.py:67 assets/models/asset.py:92
#: assets/models/domain.py:50 assets/templates/assets/admin_user_assets.html:50
#: assets/templates/assets/asset_detail.html:72
#: assets/templates/assets/domain_gateway_list.html:69
#: assets/templates/assets/system_user_asset.html:52
#: assets/templates/assets/user_asset_list.html:164
#: settings/templates/settings/replay_storage_create.html:59
msgid "Port"
msgstr "端口"
#: assets/models/asset.py:87 assets/models/domain.py:49
#: assets/templates/assets/_asset_list_modal.html:46
#: assets/templates/assets/_asset_list_modal.html:46
#: assets/templates/assets/admin_user_assets.html:49
#: assets/templates/assets/admin_user_assets.html:49
#: assets/templates/assets/asset_detail.html:64
#: assets/templates/assets/asset_detail.html:64
...
@@ -811,7 +826,7 @@ msgstr "使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig"
...
@@ -811,7 +826,7 @@ msgstr "使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig"
msgid "IP"
msgid "IP"
msgstr "IP"
msgstr "IP"
#: assets/models/asset.py:
75
assets/templates/assets/_asset_list_modal.html:45
#: assets/models/asset.py:
88
assets/templates/assets/_asset_list_modal.html:45
#: assets/templates/assets/_asset_user_auth_modal.html:9
#: assets/templates/assets/_asset_user_auth_modal.html:9
#: assets/templates/assets/_asset_user_view_auth_modal.html:25
#: assets/templates/assets/_asset_user_view_auth_modal.html:25
#: assets/templates/assets/admin_user_assets.html:48
#: assets/templates/assets/admin_user_assets.html:48
...
@@ -828,8 +843,9 @@ msgstr "IP"
...
@@ -828,8 +843,9 @@ msgstr "IP"
msgid "Hostname"
msgid "Hostname"
msgstr "主机名"
msgstr "主机名"
#: assets/models/asset.py:76 assets/models/domain.py:51
#: assets/models/asset.py:91 assets/models/asset.py:94
#: assets/models/user.py:136 assets/templates/assets/asset_detail.html:76
#: assets/models/domain.py:51 assets/models/user.py:136
#: assets/templates/assets/asset_detail.html:76
#: assets/templates/assets/domain_gateway_list.html:70
#: assets/templates/assets/domain_gateway_list.html:70
#: assets/templates/assets/system_user_detail.html:70
#: assets/templates/assets/system_user_detail.html:70
#: assets/templates/assets/system_user_list.html:53
#: assets/templates/assets/system_user_list.html:53
...
@@ -838,108 +854,98 @@ msgstr "主机名"
...
@@ -838,108 +854,98 @@ msgstr "主机名"
msgid "Protocol"
msgid "Protocol"
msgstr "协议"
msgstr "协议"
#: assets/models/asset.py:77 assets/models/domain.py:50
#: assets/models/asset.py:95 assets/templates/assets/asset_detail.html:108
#: assets/templates/assets/admin_user_assets.html:50
#: assets/templates/assets/asset_detail.html:72
#: assets/templates/assets/domain_gateway_list.html:69
#: assets/templates/assets/system_user_asset.html:52
#: assets/templates/assets/user_asset_list.html:164
#: settings/templates/settings/replay_storage_create.html:59
msgid "Port"
msgstr "端口"
#: assets/models/asset.py:78 assets/templates/assets/asset_detail.html:108
#: assets/templates/assets/user_asset_list.html:166
#: assets/templates/assets/user_asset_list.html:166
msgid "Platform"
msgid "Platform"
msgstr "系统平台"
msgstr "系统平台"
#: assets/models/asset.py:
81
assets/models/cmd_filter.py:21
#: assets/models/asset.py:
98
assets/models/cmd_filter.py:21
#: assets/models/domain.py:54 assets/models/label.py:22
#: assets/models/domain.py:54 assets/models/label.py:22
#: assets/templates/assets/asset_detail.html:116
#: assets/templates/assets/asset_detail.html:116
#: assets/templates/assets/user_asset_list.html:170
#: assets/templates/assets/user_asset_list.html:170
msgid "Is active"
msgid "Is active"
msgstr "激活"
msgstr "激活"
#: assets/models/asset.py:
87
assets/templates/assets/asset_detail.html:68
#: assets/models/asset.py:
104
assets/templates/assets/asset_detail.html:68
msgid "Public IP"
msgid "Public IP"
msgstr "公网IP"
msgstr "公网IP"
#: assets/models/asset.py:
88
assets/templates/assets/asset_detail.html:124
#: assets/models/asset.py:
105
assets/templates/assets/asset_detail.html:124
msgid "Asset number"
msgid "Asset number"
msgstr "资产编号"
msgstr "资产编号"
#: assets/models/asset.py:
91
assets/templates/assets/asset_detail.html:88
#: assets/models/asset.py:
108
assets/templates/assets/asset_detail.html:88
msgid "Vendor"
msgid "Vendor"
msgstr "制造商"
msgstr "制造商"
#: assets/models/asset.py:
92
assets/templates/assets/asset_detail.html:92
#: assets/models/asset.py:
109
assets/templates/assets/asset_detail.html:92
msgid "Model"
msgid "Model"
msgstr "型号"
msgstr "型号"
#: assets/models/asset.py:
93
assets/templates/assets/asset_detail.html:120
#: assets/models/asset.py:
110
assets/templates/assets/asset_detail.html:120
msgid "Serial number"
msgid "Serial number"
msgstr "序列号"
msgstr "序列号"
#: assets/models/asset.py:
95
#: assets/models/asset.py:
112
msgid "CPU model"
msgid "CPU model"
msgstr "CPU型号"
msgstr "CPU型号"
#: assets/models/asset.py:
96
#: assets/models/asset.py:
113
#: xpack/plugins/license/templates/license/license_detail.html:80
#: xpack/plugins/license/templates/license/license_detail.html:80
msgid "CPU count"
msgid "CPU count"
msgstr "CPU数量"
msgstr "CPU数量"
#: assets/models/asset.py:
97
#: assets/models/asset.py:
114
msgid "CPU cores"
msgid "CPU cores"
msgstr "CPU核数"
msgstr "CPU核数"
#: assets/models/asset.py:
98
#: assets/models/asset.py:
115
msgid "CPU vcpus"
msgid "CPU vcpus"
msgstr "CPU总数"
msgstr "CPU总数"
#: assets/models/asset.py:
99
assets/templates/assets/asset_detail.html:100
#: assets/models/asset.py:
116
assets/templates/assets/asset_detail.html:100
msgid "Memory"
msgid "Memory"
msgstr "内存"
msgstr "内存"
#: assets/models/asset.py:1
00
#: assets/models/asset.py:1
17
msgid "Disk total"
msgid "Disk total"
msgstr "硬盘大小"
msgstr "硬盘大小"
#: assets/models/asset.py:1
01
#: assets/models/asset.py:1
18
msgid "Disk info"
msgid "Disk info"
msgstr "硬盘信息"
msgstr "硬盘信息"
#: assets/models/asset.py:1
03
assets/templates/assets/asset_detail.html:112
#: assets/models/asset.py:1
20
assets/templates/assets/asset_detail.html:112
#: assets/templates/assets/user_asset_list.html:167
#: assets/templates/assets/user_asset_list.html:167
msgid "OS"
msgid "OS"
msgstr "操作系统"
msgstr "操作系统"
#: assets/models/asset.py:1
04
#: assets/models/asset.py:1
21
msgid "OS version"
msgid "OS version"
msgstr "系统版本"
msgstr "系统版本"
#: assets/models/asset.py:1
05
#: assets/models/asset.py:1
22
msgid "OS arch"
msgid "OS arch"
msgstr "系统架构"
msgstr "系统架构"
#: assets/models/asset.py:1
06
#: assets/models/asset.py:1
23
msgid "Hostname raw"
msgid "Hostname raw"
msgstr "主机名原始"
msgstr "主机名原始"
#: assets/models/asset.py:1
08 assets/templates/assets/asset_create.html:34
#: assets/models/asset.py:1
25 assets/templates/assets/asset_create.html:46
#: assets/templates/assets/asset_detail.html:231
#: assets/templates/assets/asset_detail.html:231
#: assets/templates/assets/asset_update.html:39 templates/_nav.html:26
#: assets/templates/assets/asset_update.html:39 templates/_nav.html:26
msgid "Labels"
msgid "Labels"
msgstr "标签管理"
msgstr "标签管理"
#: assets/models/asset.py:1
17
assets/models/base.py:38
#: assets/models/asset.py:1
34
assets/models/base.py:38
#: assets/serializers/admin_user.py:22 assets/serializers/system_user.py:19
#: assets/serializers/admin_user.py:22 assets/serializers/system_user.py:19
#: assets/templates/assets/admin_user_list.html:51
#: assets/templates/assets/admin_user_list.html:51
#: assets/templates/assets/system_user_list.html:57
#: assets/templates/assets/system_user_list.html:57
msgid "Unreachable"
msgid "Unreachable"
msgstr "不可达"
msgstr "不可达"
#: assets/models/asset.py:1
18
assets/models/base.py:39
#: assets/models/asset.py:1
35
assets/models/base.py:39
#: assets/serializers/admin_user.py:24 assets/serializers/system_user.py:27
#: assets/serializers/admin_user.py:24 assets/serializers/system_user.py:27
#: assets/templates/assets/admin_user_assets.html:51
#: assets/templates/assets/admin_user_assets.html:51
#: assets/templates/assets/admin_user_list.html:50
#: assets/templates/assets/admin_user_list.html:50
...
@@ -951,7 +957,7 @@ msgstr "不可达"
...
@@ -951,7 +957,7 @@ msgstr "不可达"
msgid "Reachable"
msgid "Reachable"
msgstr "可连接"
msgstr "可连接"
#: assets/models/asset.py:1
19
assets/models/base.py:40
#: assets/models/asset.py:1
36
assets/models/base.py:40
#: authentication/utils.py:9 xpack/plugins/license/models.py:78
#: authentication/utils.py:9 xpack/plugins/license/models.py:78
msgid "Unknown"
msgid "Unknown"
msgstr "未知"
msgstr "未知"
...
@@ -1198,18 +1204,22 @@ msgstr "%(value)s is not an even number"
...
@@ -1198,18 +1204,22 @@ msgstr "%(value)s is not an even number"
msgid "Date updated"
msgid "Date updated"
msgstr "更新日期"
msgstr "更新日期"
#: assets/serializers/asset.py:
43
#: assets/serializers/asset.py:
52
msgid "Hardware info"
msgid "Hardware info"
msgstr "硬件信息"
msgstr "硬件信息"
#: assets/serializers/asset.py:
44
#: assets/serializers/asset.py:
53
msgid "Connectivity"
msgid "Connectivity"
msgstr "连接"
msgstr "连接"
#: assets/serializers/asset.py:
45
#: assets/serializers/asset.py:
54
msgid "Org name"
msgid "Org name"
msgstr "组织名"
msgstr "组织名"
#: assets/serializers/asset.py:70
msgid "Protocol duplicate: {}"
msgstr "协议重复: {}"
#: assets/serializers/asset_user.py:23 users/forms.py:230
#: assets/serializers/asset_user.py:23 users/forms.py:230
#: users/models/user.py:91 users/templates/users/first_login.html:42
#: users/models/user.py:91 users/templates/users/first_login.html:42
#: users/templates/users/user_password_update.html:46
#: users/templates/users/user_password_update.html:46
...
@@ -1341,7 +1351,7 @@ msgstr "启用MFA"
...
@@ -1341,7 +1351,7 @@ msgstr "启用MFA"
msgid "Import assets"
msgid "Import assets"
msgstr "导入资产"
msgstr "导入资产"
#: assets/templates/assets/_asset_list_modal.html:7 assets/views/asset.py:5
4
#: assets/templates/assets/_asset_list_modal.html:7 assets/views/asset.py:5
3
#: templates/_nav.html:22 xpack/plugins/change_auth_plan/views.py:110
#: templates/_nav.html:22 xpack/plugins/change_auth_plan/views.py:110
msgid "Asset list"
msgid "Asset list"
msgstr "资产列表"
msgstr "资产列表"
...
@@ -1437,7 +1447,7 @@ msgid "Basic"
...
@@ -1437,7 +1447,7 @@ msgid "Basic"
msgstr "基本"
msgstr "基本"
#: assets/templates/assets/_system_user.html:44
#: assets/templates/assets/_system_user.html:44
#: assets/templates/assets/asset_create.html:
26
#: assets/templates/assets/asset_create.html:
38
#: assets/templates/assets/asset_update.html:31
#: assets/templates/assets/asset_update.html:31
#: assets/templates/assets/gateway_create_update.html:45
#: assets/templates/assets/gateway_create_update.html:45
#: users/templates/users/_user.html:21
#: users/templates/users/_user.html:21
...
@@ -1449,7 +1459,7 @@ msgid "Auto generate key"
...
@@ -1449,7 +1459,7 @@ msgid "Auto generate key"
msgstr "自动生成密钥"
msgstr "自动生成密钥"
#: assets/templates/assets/_system_user.html:69
#: assets/templates/assets/_system_user.html:69
#: assets/templates/assets/asset_create.html:
60
#: assets/templates/assets/asset_create.html:
72
#: assets/templates/assets/asset_update.html:64
#: assets/templates/assets/asset_update.html:64
#: assets/templates/assets/gateway_create_update.html:53
#: assets/templates/assets/gateway_create_update.html:53
#: perms/templates/perms/asset_permission_create_update.html:53
#: perms/templates/perms/asset_permission_create_update.html:53
...
@@ -1470,7 +1480,7 @@ msgstr "更新系统用户"
...
@@ -1470,7 +1480,7 @@ msgstr "更新系统用户"
#: assets/templates/assets/_user_asset_detail_modal.html:11
#: assets/templates/assets/_user_asset_detail_modal.html:11
#: assets/templates/assets/asset_asset_user_list.html:13
#: assets/templates/assets/asset_asset_user_list.html:13
#: assets/templates/assets/asset_detail.html:20 assets/views/asset.py:
189
#: assets/templates/assets/asset_detail.html:20 assets/views/asset.py:
208
msgid "Asset detail"
msgid "Asset detail"
msgstr "资产详情"
msgstr "资产详情"
...
@@ -1611,7 +1621,7 @@ msgid "Please select file"
...
@@ -1611,7 +1621,7 @@ msgid "Please select file"
msgstr "选择文件"
msgstr "选择文件"
#: assets/templates/assets/asset_asset_user_list.html:16
#: assets/templates/assets/asset_asset_user_list.html:16
#: assets/templates/assets/asset_detail.html:23 assets/views/asset.py:
70
#: assets/templates/assets/asset_detail.html:23 assets/views/asset.py:
69
msgid "Asset user list"
msgid "Asset user list"
msgstr "资产用户列表"
msgstr "资产用户列表"
...
@@ -1643,6 +1653,10 @@ msgstr "选择需要修改属性"
...
@@ -1643,6 +1653,10 @@ msgstr "选择需要修改属性"
msgid "Select all"
msgid "Select all"
msgstr "全选"
msgstr "全选"
#: assets/templates/assets/asset_create.html:24
msgid "Protocols"
msgstr "协议"
#: assets/templates/assets/asset_detail.html:96
#: assets/templates/assets/asset_detail.html:96
msgid "CPU"
msgid "CPU"
msgstr "CPU"
msgstr "CPU"
...
@@ -1690,7 +1704,7 @@ msgstr ""
...
@@ -1690,7 +1704,7 @@ msgstr ""
"左侧是资产树,右击可以新建、删除、更改树节点,授权资产也是以节点方式组织的,"
"左侧是资产树,右击可以新建、删除、更改树节点,授权资产也是以节点方式组织的,"
"右侧是属于该节点下的资产"
"右侧是属于该节点下的资产"
#: assets/templates/assets/asset_list.html:69 assets/views/asset.py:1
07
#: assets/templates/assets/asset_list.html:69 assets/views/asset.py:1
25
msgid "Create asset"
msgid "Create asset"
msgstr "创建资产"
msgstr "创建资产"
...
@@ -2033,23 +2047,23 @@ msgstr "管理用户列表"
...
@@ -2033,23 +2047,23 @@ msgstr "管理用户列表"
msgid "Admin user detail"
msgid "Admin user detail"
msgstr "管理用户详情"
msgstr "管理用户详情"
#: assets/views/asset.py:8
1
templates/_nav_user.html:4
#: assets/views/asset.py:8
0
templates/_nav_user.html:4
msgid "My assets"
msgid "My assets"
msgstr "我的资产"
msgstr "我的资产"
#: assets/views/asset.py:1
21
#: assets/views/asset.py:1
40
msgid "Bulk update asset success"
msgid "Bulk update asset success"
msgstr "批量更新资产成功"
msgstr "批量更新资产成功"
#: assets/views/asset.py:1
48
#: assets/views/asset.py:1
67
msgid "Bulk update asset"
msgid "Bulk update asset"
msgstr "批量更新资产"
msgstr "批量更新资产"
#: assets/views/asset.py:1
65
#: assets/views/asset.py:1
84
msgid "Update asset"
msgid "Update asset"
msgstr "更新资产"
msgstr "更新资产"
#: assets/views/asset.py:3
06
#: assets/views/asset.py:3
25
msgid "already exists"
msgid "already exists"
msgstr "已经存在"
msgstr "已经存在"
...
@@ -2597,18 +2611,35 @@ msgstr ""
...
@@ -2597,18 +2611,35 @@ msgstr ""
msgid "Encrypt field using Secret Key"
msgid "Encrypt field using Secret Key"
msgstr ""
msgstr ""
#: common/mixins.py:3
5
#: common/mixins.py:3
6
msgid "is discard"
msgid "is discard"
msgstr ""
msgstr ""
#: common/mixins.py:3
6
#: common/mixins.py:3
7
msgid "discard time"
msgid "discard time"
msgstr ""
msgstr ""
#: common/validators.py:7
#: common/mixins.py:210
#, fuzzy, python-format
msgid "%(name)s was %(action)s successfully"
msgstr "%(name)s %(action)s成功"
#: common/mixins.py:211
msgid "create"
msgstr "创建"
#: common/mixins.py:211
msgid "update"
msgstr "更新"
#: common/validators.py:11
msgid "Special char not allowed"
msgid "Special char not allowed"
msgstr "不能包含特殊字符"
msgstr "不能包含特殊字符"
#: common/validators.py:23
msgid "This field must be unique."
msgstr ""
#: jumpserver/views.py:185
#: jumpserver/views.py:185
msgid ""
msgid ""
"<div>Luna is a separately deployed program, you need to deploy Luna, coco, "
"<div>Luna is a separately deployed program, you need to deploy Luna, coco, "
...
@@ -2960,7 +2991,7 @@ msgstr "命令执行列表"
...
@@ -2960,7 +2991,7 @@ msgstr "命令执行列表"
msgid "Command execution"
msgid "Command execution"
msgstr "命令执行"
msgstr "命令执行"
#: orgs/mixins.py:8
1
orgs/models.py:24
#: orgs/mixins.py:8
3
orgs/models.py:24
msgid "Organization"
msgid "Organization"
msgstr "组织管理"
msgstr "组织管理"
...
@@ -3161,12 +3192,12 @@ msgstr "添加用户组"
...
@@ -3161,12 +3192,12 @@ msgstr "添加用户组"
#: perms/views/asset_permission.py:33 perms/views/asset_permission.py:65
#: perms/views/asset_permission.py:33 perms/views/asset_permission.py:65
#: perms/views/asset_permission.py:80 perms/views/asset_permission.py:95
#: perms/views/asset_permission.py:80 perms/views/asset_permission.py:95
#: perms/views/asset_permission.py:130 perms/views/asset_permission.py:162
#: perms/views/asset_permission.py:130 perms/views/asset_permission.py:162
#: perms/views/remote_app_permission.py:3
3
#: perms/views/remote_app_permission.py:3
2
#: perms/views/remote_app_permission.py:4
8
#: perms/views/remote_app_permission.py:4
7
#: perms/views/remote_app_permission.py:6
3
#: perms/views/remote_app_permission.py:6
2
#: perms/views/remote_app_permission.py:7
6
#: perms/views/remote_app_permission.py:7
5
#: perms/views/remote_app_permission.py:10
2
#: perms/views/remote_app_permission.py:10
1
#: perms/views/remote_app_permission.py:13
8
templates/_nav.html:39
#: perms/views/remote_app_permission.py:13
7
templates/_nav.html:39
#: xpack/plugins/orgs/templates/orgs/org_list.html:21
#: xpack/plugins/orgs/templates/orgs/org_list.html:21
msgid "Perms"
msgid "Perms"
msgstr "权限管理"
msgstr "权限管理"
...
@@ -3195,27 +3226,27 @@ msgstr "资产授权用户列表"
...
@@ -3195,27 +3226,27 @@ msgstr "资产授权用户列表"
msgid "Asset permission asset list"
msgid "Asset permission asset list"
msgstr "资产授权资产列表"
msgstr "资产授权资产列表"
#: perms/views/remote_app_permission.py:3
4
#: perms/views/remote_app_permission.py:3
3
msgid "RemoteApp permission list"
msgid "RemoteApp permission list"
msgstr "远程应用授权列表"
msgstr "远程应用授权列表"
#: perms/views/remote_app_permission.py:4
9
#: perms/views/remote_app_permission.py:4
8
msgid "Create RemoteApp permission"
msgid "Create RemoteApp permission"
msgstr "创建远程应用授权规则"
msgstr "创建远程应用授权规则"
#: perms/views/remote_app_permission.py:6
4
#: perms/views/remote_app_permission.py:6
3
msgid "Update RemoteApp permission"
msgid "Update RemoteApp permission"
msgstr "更新远程应用授权规则"
msgstr "更新远程应用授权规则"
#: perms/views/remote_app_permission.py:7
7
#: perms/views/remote_app_permission.py:7
6
msgid "RemoteApp permission detail"
msgid "RemoteApp permission detail"
msgstr "远程应用授权详情"
msgstr "远程应用授权详情"
#: perms/views/remote_app_permission.py:10
3
#: perms/views/remote_app_permission.py:10
2
msgid "RemoteApp permission user list"
msgid "RemoteApp permission user list"
msgstr "远程应用授权用户列表"
msgstr "远程应用授权用户列表"
#: perms/views/remote_app_permission.py:13
9
#: perms/views/remote_app_permission.py:13
8
msgid "RemoteApp permission RemoteApp list"
msgid "RemoteApp permission RemoteApp list"
msgstr "远程应用授权远程应用列表"
msgstr "远程应用授权远程应用列表"
...
@@ -3861,7 +3892,7 @@ msgid "File manager"
...
@@ -3861,7 +3892,7 @@ msgid "File manager"
msgstr "文件管理"
msgstr "文件管理"
#: templates/_nav.html:68 terminal/views/command.py:50
#: templates/_nav.html:68 terminal/views/command.py:50
#: terminal/views/session.py:7
5 terminal/views/session.py:93
#: terminal/views/session.py:7
4 terminal/views/session.py:92
#: terminal/views/session.py:115 terminal/views/terminal.py:31
#: terminal/views/session.py:115 terminal/views/terminal.py:31
#: terminal/views/terminal.py:46 terminal/views/terminal.py:58
#: terminal/views/terminal.py:46 terminal/views/terminal.py:58
msgid "Terminal"
msgid "Terminal"
...
@@ -4241,11 +4272,11 @@ msgstr "接受终端注册"
...
@@ -4241,11 +4272,11 @@ msgstr "接受终端注册"
msgid "Info"
msgid "Info"
msgstr "信息"
msgstr "信息"
#: terminal/views/session.py:7
6
#: terminal/views/session.py:7
5
msgid "Session online list"
msgid "Session online list"
msgstr "在线会话"
msgstr "在线会话"
#: terminal/views/session.py:9
4
#: terminal/views/session.py:9
3
msgid "Session offline list"
msgid "Session offline list"
msgstr "离线会话"
msgstr "离线会话"
...
...
apps/orgs/mixins.py
View file @
a5b874e2
...
@@ -9,8 +9,10 @@ from django.forms import ModelForm
...
@@ -9,8 +9,10 @@ from django.forms import ModelForm
from
django.http.response
import
HttpResponseForbidden
from
django.http.response
import
HttpResponseForbidden
from
django.core.exceptions
import
ValidationError
from
django.core.exceptions
import
ValidationError
from
rest_framework
import
serializers
from
rest_framework
import
serializers
from
rest_framework.validators
import
UniqueTogetherValidator
from
common.utils
import
get_logger
from
common.utils
import
get_logger
from
common.validators
import
ProjectUniqueValidator
from
.utils
import
(
from
.utils
import
(
current_org
,
set_current_org
,
set_to_root_org
,
get_current_org_id
current_org
,
set_current_org
,
set_to_root_org
,
get_current_org_id
)
)
...
@@ -214,3 +216,14 @@ class OrgResourceSerializerMixin(serializers.Serializer):
...
@@ -214,3 +216,14 @@ class OrgResourceSerializerMixin(serializers.Serializer):
(同时为serializer.is_valid()对Model的unique_together校验做准备)
(同时为serializer.is_valid()对Model的unique_together校验做准备)
"""
"""
org_id
=
serializers
.
HiddenField
(
default
=
get_current_org_id
)
org_id
=
serializers
.
HiddenField
(
default
=
get_current_org_id
)
def
get_validators
(
self
):
_validators
=
super
()
.
get_validators
()
validators
=
[]
for
v
in
_validators
:
if
isinstance
(
v
,
UniqueTogetherValidator
)
\
and
"org_id"
in
v
.
fields
:
v
=
ProjectUniqueValidator
(
v
.
queryset
,
v
.
fields
)
validators
.
append
(
v
)
return
validators
apps/perms/hands.py
View file @
a5b874e2
...
@@ -3,11 +3,12 @@
...
@@ -3,11 +3,12 @@
from
common.permissions
import
AdminUserRequiredMixin
from
common.permissions
import
AdminUserRequiredMixin
from
users.models
import
User
,
UserGroup
from
users.models
import
User
,
UserGroup
from
assets.models
import
Asset
,
SystemUser
,
Node
,
RemoteApp
from
assets.models
import
Asset
,
SystemUser
,
Node
from
assets.serializers
import
(
from
assets.serializers
import
(
AssetGrantedSerializer
,
NodeSerializer
AssetGrantedSerializer
,
NodeSerializer
)
)
from
applications.serializers
import
RemoteAppSerializer
from
applications.serializers
import
RemoteAppSerializer
from
applications.models
import
RemoteApp
apps/perms/views/remote_app_permission.py
View file @
a5b874e2
...
@@ -11,9 +11,8 @@ from django.conf import settings
...
@@ -11,9 +11,8 @@ from django.conf import settings
from
common.permissions
import
AdminUserRequiredMixin
from
common.permissions
import
AdminUserRequiredMixin
from
orgs.utils
import
current_org
from
orgs.utils
import
current_org
from
users.models
import
UserGroup
from
assets.models
import
RemoteApp
from
..hands
import
RemoteApp
,
UserGroup
from
..models
import
RemoteAppPermission
from
..models
import
RemoteAppPermission
from
..forms
import
RemoteAppPermissionCreateUpdateForm
from
..forms
import
RemoteAppPermissionCreateUpdateForm
...
...
apps/static/css/jumpserver.css
View file @
a5b874e2
...
@@ -453,4 +453,16 @@ div.dataTables_wrapper div.dataTables_filter {
...
@@ -453,4 +453,16 @@ div.dataTables_wrapper div.dataTables_filter {
#tree-refresh
.fa-refresh
{
#tree-refresh
.fa-refresh
{
font
:
normal
normal
normal
14px
/
1
FontAwesome
!important
;
font
:
normal
normal
normal
14px
/
1
FontAwesome
!important
;
}
}
\ No newline at end of file
.select2-selection__rendered
span
.select2-selection
,
.select2-container
.select2-selection--single
,
.select2-selection__arrow
{
height
:
34px
!important
;
}
.select2-selection
{
border-radius
:
0
!important
;
}
span
.select2-selection__placeholder
{
line-height
:
34px
!important
;
}
apps/static/js/jumpserver.js
View file @
a5b874e2
...
@@ -165,11 +165,13 @@ function formSubmit(props) {
...
@@ -165,11 +165,13 @@ function formSubmit(props) {
/*
/*
{
{
"form": $("form"),
"form": $("form"),
"data": {},
"url": "",
"url": "",
"method": "POST",
"method": "POST",
"redirect_to": "",
"redirect_to": "",
"success": function(data, textStatue, jqXHR){},
"success": function(data, textStatue, jqXHR){},
"error": function(jqXHR, textStatus, errorThrown) {}
"error": function(jqXHR, textStatus, errorThrown) {},
"message": "",
}
}
*/
*/
props
=
props
||
{};
props
=
props
||
{};
...
@@ -183,6 +185,10 @@ function formSubmit(props) {
...
@@ -183,6 +185,10 @@ function formSubmit(props) {
dataType
:
props
.
data_type
||
"json"
dataType
:
props
.
data_type
||
"json"
}).
done
(
function
(
data
,
textState
,
jqXHR
)
{
}).
done
(
function
(
data
,
textState
,
jqXHR
)
{
if
(
redirect_to
)
{
if
(
redirect_to
)
{
if
(
props
.
message
)
{
var
messages
=
"ed65330a45559c87345a0eb6ac7812d18d0d8976$[[
\"
__json_message
\"
\
0540
\
05425
\
054
\"
asdfasdf
\\
u521b
\\
u5efa
\\
u6210
\\
u529f
\"
]]"
setCookie
(
"messages"
,
messages
)
}
location
.
href
=
redirect_to
;
location
.
href
=
redirect_to
;
}
else
if
(
typeof
props
.
success
===
'function'
)
{
}
else
if
(
typeof
props
.
success
===
'function'
)
{
return
props
.
success
(
data
,
textState
,
jqXHR
);
return
props
.
success
(
data
,
textState
,
jqXHR
);
...
@@ -230,7 +236,15 @@ function formSubmit(props) {
...
@@ -230,7 +236,15 @@ function formSubmit(props) {
var
help_msg
=
v
.
join
(
"<br/>"
)
;
var
help_msg
=
v
.
join
(
"<br/>"
)
;
helpBlockRef
.
html
(
help_msg
);
helpBlockRef
.
html
(
help_msg
);
}
else
{
}
else
{
noneFieldErrorMsg
+=
v
+
'<br/>'
;
$
.
each
(
v
,
function
(
kk
,
vv
)
{
if
(
typeof
errors
===
"object"
)
{
$
.
each
(
vv
,
function
(
kkk
,
vvv
)
{
noneFieldErrorMsg
+=
" "
+
vvv
+
'<br/>'
;
})
}
else
{
noneFieldErrorMsg
+=
vv
+
'<br/>'
;
}
})
}
}
});
});
if
(
noneFieldErrorRef
.
length
===
1
&&
noneFieldErrorMsg
!==
''
)
{
if
(
noneFieldErrorRef
.
length
===
1
&&
noneFieldErrorMsg
!==
''
)
{
...
...
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