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
1fe18e80
Unverified
Commit
1fe18e80
authored
Aug 23, 2019
by
老广
Committed by
GitHub
Aug 23, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Bugfix (#3153)
* [Update] 修改一部分bug * [Update] 修改一些
parent
de1a08a5
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
146 additions
and
175 deletions
+146
-175
asset.py
apps/assets/api/asset.py
+3
-3
node.py
apps/assets/api/node.py
+7
-6
asset.py
apps/assets/models/asset.py
+5
-28
node.py
apps/assets/models/node.py
+68
-64
user.py
apps/assets/models/user.py
+2
-0
signals_handler.py
apps/assets/signals_handler.py
+49
-41
asset.py
apps/assets/views/asset.py
+2
-2
_access_key_modal.html
...ntication/templates/authentication/_access_key_modal.html
+2
-2
signals_handler.py
apps/orgs/signals_handler.py
+1
-1
asset_permission.py
apps/perms/models/asset_permission.py
+1
-0
signals_handler.py
apps/perms/signals_handler.py
+1
-10
asset_permission.py
apps/perms/utils/asset_permission.py
+3
-17
asset_permission.py
apps/perms/views/asset_permission.py
+2
-1
No files found.
apps/assets/api/asset.py
View file @
1fe18e80
...
...
@@ -63,15 +63,15 @@ class AssetViewSet(LabelFilter, OrgBulkModelViewSet):
show_current_asset
=
self
.
request
.
query_params
.
get
(
"show_current_asset"
)
in
(
'1'
,
'true'
)
# 当前节点是顶层节点, 并且仅显示直接资产
if
node
.
is_root
()
and
show_current_asset
:
if
node
.
is_
org_
root
()
and
show_current_asset
:
queryset
=
queryset
.
filter
(
Q
(
nodes
=
node_id
)
|
Q
(
nodes__isnull
=
True
)
)
.
distinct
()
# 当前节点是顶层节点,显示所有资产
elif
node
.
is_root
()
and
not
show_current_asset
:
elif
node
.
is_
org_
root
()
and
not
show_current_asset
:
return
queryset
# 当前节点不是鼎城节点,只显示直接资产
elif
not
node
.
is_root
()
and
show_current_asset
:
elif
not
node
.
is_
org_
root
()
and
show_current_asset
:
queryset
=
queryset
.
filter
(
nodes
=
node
)
else
:
children
=
node
.
get_all_children
(
with_self
=
True
)
...
...
apps/assets/api/node.py
View file @
1fe18e80
...
...
@@ -50,13 +50,13 @@ class NodeViewSet(OrgModelViewSet):
# 仅支持根节点指直接创建,子节点下的节点需要通过children接口创建
def
perform_create
(
self
,
serializer
):
child_key
=
Node
.
root
()
.
get_next_child_key
()
child_key
=
Node
.
org_
root
()
.
get_next_child_key
()
serializer
.
validated_data
[
"key"
]
=
child_key
serializer
.
save
()
def
perform_update
(
self
,
serializer
):
node
=
self
.
get_object
()
if
node
.
is_root
()
and
node
.
value
!=
serializer
.
validated_data
[
'value'
]:
if
node
.
is_
org_
root
()
and
node
.
value
!=
serializer
.
validated_data
[
'value'
]:
msg
=
_
(
"You can't update the root node name"
)
raise
ValidationError
({
"error"
:
msg
})
return
super
()
.
perform_update
(
serializer
)
...
...
@@ -97,6 +97,7 @@ class NodeChildrenApi(generics.ListCreateAPIView):
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
serializers
.
NodeSerializer
instance
=
None
is_initial
=
False
def
initial
(
self
,
request
,
*
args
,
**
kwargs
):
self
.
instance
=
self
.
get_object
()
...
...
@@ -117,7 +118,8 @@ class NodeChildrenApi(generics.ListCreateAPIView):
pk
=
self
.
kwargs
.
get
(
'pk'
)
or
self
.
request
.
query_params
.
get
(
'id'
)
key
=
self
.
request
.
query_params
.
get
(
"key"
)
if
not
pk
and
not
key
:
node
=
Node
.
root
()
node
=
Node
.
org_root
()
self
.
is_initial
=
True
return
node
if
pk
:
node
=
get_object_or_404
(
Node
,
pk
=
pk
)
...
...
@@ -130,7 +132,7 @@ class NodeChildrenApi(generics.ListCreateAPIView):
if
not
self
.
instance
:
return
Node
.
objects
.
none
()
if
self
.
i
nstance
.
is_root
()
:
if
self
.
i
s_initial
:
with_self
=
True
else
:
with_self
=
False
...
...
@@ -234,7 +236,7 @@ class NodeRemoveAssetsApi(generics.UpdateAPIView):
def
perform_update
(
self
,
serializer
):
assets
=
serializer
.
validated_data
.
get
(
'assets'
)
instance
=
self
.
get_object
()
if
instance
!=
Node
.
root
():
if
instance
!=
Node
.
org_
root
():
instance
.
assets
.
remove
(
*
tuple
(
assets
))
else
:
assets
=
[
asset
for
asset
in
assets
if
asset
.
nodes
.
count
()
>
1
]
...
...
@@ -287,5 +289,4 @@ class RefreshAssetsAmount(APIView):
model
=
Node
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
self
.
model
.
expire_nodes_assets_amount
()
return
Response
(
"Ok"
)
apps/assets/models/asset.py
View file @
1fe18e80
...
...
@@ -6,8 +6,7 @@ import uuid
import
logging
import
random
from
functools
import
reduce
from
collections
import
OrderedDict
,
defaultdict
from
django.core.cache
import
cache
from
collections
import
OrderedDict
from
django.db
import
models
from
django.utils.translation
import
ugettext_lazy
as
_
...
...
@@ -32,7 +31,7 @@ def default_cluster():
def
default_node
():
try
:
from
.node
import
Node
root
=
Node
.
root
()
root
=
Node
.
org_
root
()
return
root
except
:
return
None
...
...
@@ -103,33 +102,11 @@ class NodesRelationMixin:
id
=
""
_all_nodes_keys
=
None
@classmethod
def
get_all_nodes_keys
(
cls
):
"""
:return: {asset.id: [node.key, ]}
"""
from
.node
import
Node
cache_key
=
cls
.
ALL_ASSET_NODES_CACHE_KEY
cached
=
cache
.
get
(
cache_key
)
if
cached
:
return
cached
assets
=
Asset
.
objects
.
all
()
.
only
(
'id'
)
.
prefetch_related
(
models
.
Prefetch
(
'nodes'
,
queryset
=
Node
.
objects
.
all
()
.
only
(
'key'
))
)
assets_nodes_keys
=
{}
for
asset
in
assets
:
assets_nodes_keys
[
asset
.
id
]
=
[
n
.
key
for
n
in
asset
.
nodes
.
all
()]
cache
.
set
(
cache_key
,
assets_nodes_keys
,
cls
.
CACHE_TIME
)
return
assets_nodes_keys
@classmethod
def
expire_all_nodes_keys_cache
(
cls
):
cache_key
=
cls
.
ALL_ASSET_NODES_CACHE_KEY
cache
.
delete
(
cache_key
)
def
get_nodes
(
self
):
from
.node
import
Node
nodes
=
self
.
nodes
.
all
()
or
[
Node
.
root
()]
nodes
=
self
.
nodes
.
all
()
if
not
nodes
:
nodes
=
Node
.
objects
.
filter
(
id
=
Node
.
org_root
()
.
id
)
return
nodes
def
get_all_nodes
(
self
,
flat
=
False
):
...
...
apps/assets/models/node.py
View file @
1fe18e80
...
...
@@ -24,40 +24,34 @@ class NodeQuerySet(models.QuerySet):
class
TreeMixin
:
t
ime_tree_updated
=
None
t
ime_tree_updated
_cache_key
=
'NODE_TREE_CREATED_AT'
tree_cache_time
=
3600
t
ree_created_time
=
None
t
ree_updated_time
_cache_key
=
'NODE_TREE_CREATED_AT'
tree_
update_time_
cache_time
=
3600
_tree_service
=
None
@classmethod
def
tree
(
cls
):
# Todo: 有待优化, 因为每次刷新都会导致其他节点的tree失效
# Todo: ungroup node
# Todo: 有待优化, 因为每次刷新都会导致其他节点的tree失效 完成
# TOdo: 游离的资产,在树上显示的数量不对
# Todo: api key页面有bug
# Todo: ungroup node
# Todo: api key页面有bug 完成
from
..utils
import
TreeService
cache_updated_time
=
cls
.
get_cache_time
()
if
not
cls
.
time_tree_updated
or
\
cache_updated_time
!=
cls
.
time_tree_updated
:
t
=
TreeService
.
new
()
cls
.
update_cache_tree
(
t
)
return
t
tree_updated_time
=
cache
.
get
(
cls
.
tree_updated_time_cache_key
,
0
)
if
not
cls
.
tree_created_time
or
\
tree_updated_time
>
cls
.
tree_created_time
:
print
(
"New tree"
)
tree
=
TreeService
.
new
()
cls
.
tree_created_time
=
time
.
time
()
cls
.
_tree_service
=
tree
return
tree
return
cls
.
_tree_service
@classmethod
def
get_cache_time
(
cls
):
return
cache
.
get
(
cls
.
time_tree_updated_cache_key
)
@classmethod
def
update_cache_tree
(
cls
,
t
):
cls
.
_tree_service
=
t
now
=
time
.
time
()
cls
.
time_tree_updated
=
now
cache
.
set
(
cls
.
time_tree_updated_cache_key
,
now
,
cls
.
tree_cache_time
)
@classmethod
def
expire_cache_tree
(
cls
):
cache
.
delete
(
cls
.
time_tree_updated_cache_key
)
key
=
cls
.
tree_updated_time_cache_key
ttl
=
cls
.
tree_update_time_cache_time
value
=
time
.
time
()
cache
.
set
(
key
,
value
,
ttl
)
@classmethod
def
refresh_tree
(
cls
):
...
...
@@ -74,6 +68,20 @@ class FamilyMixin:
__all_children
=
None
is_node
=
True
@staticmethod
def
clean_children_keys
(
nodes_keys
):
nodes_keys
=
sorted
(
list
(
nodes_keys
),
key
=
lambda
x
:
(
len
(
x
),
x
))
nodes_keys_clean
=
[]
for
key
in
nodes_keys
[::
-
1
]:
found
=
False
for
k
in
nodes_keys
:
if
key
.
startswith
(
k
+
':'
):
found
=
True
break
if
not
found
:
nodes_keys_clean
.
append
(
key
)
return
nodes_keys_clean
@property
def
children
(
self
):
return
self
.
get_children
(
with_self
=
False
)
...
...
@@ -108,7 +116,7 @@ class FamilyMixin:
@property
def
parent
(
self
):
if
self
.
is_root
():
if
self
.
is_
org_
root
():
return
self
parent_key
=
self
.
parent_key
return
Node
.
objects
.
get
(
key
=
parent_key
)
...
...
@@ -122,10 +130,10 @@ class FamilyMixin:
old_key
=
self
.
key
with
transaction
.
atomic
():
self
.
key
=
parent
.
get_next_child_key
()
self
.
save
()
for
child
in
children
:
child
.
key
=
child
.
key
.
replace
(
old_key
,
self
.
key
,
1
)
child
.
save
()
self
.
save
()
def
get_siblings
(
self
,
with_self
=
False
):
key
=
':'
.
join
(
self
.
key
.
split
(
':'
)[:
-
1
])
...
...
@@ -182,21 +190,17 @@ class FullValueMixin:
@property
def
full_value
(
self
):
if
self
.
is_root
():
if
self
.
is_
org_
root
():
return
self
.
value
if
self
.
_full_value
is
not
None
:
return
self
.
_full_value
print
(
"Get full value"
)
value
=
self
.
_tree
.
get_node_full_tag
(
self
.
key
)
return
value
class
NodeAssetsMixin
:
_assets_amount_cache_key
=
'_NODE_ASSETS_AMOUNT_{}'
_assets_cache_key
=
'_NODE_ASSETS_{}'
_assets_amount
=
None
key
=
''
cache_time
=
3600
*
24
*
7
id
=
None
@property
...
...
@@ -210,24 +214,19 @@ class NodeAssetsMixin:
amount
=
self
.
_tree
.
assets_amount
(
self
.
key
)
return
amount
# TOdo: 是否依赖tree
def
get_all_assets
(
self
):
from
.asset
import
Asset
if
self
.
is_root
():
if
self
.
is_
org_
root
():
return
Asset
.
objects
.
filter
(
org_id
=
self
.
org_id
)
assets_ids
=
self
.
_tree
.
all_assets
(
self
.
key
)
return
Asset
.
objects
.
filter
(
id__in
=
assets_ids
)
def
assets_ids
(
self
):
assets_ids
=
self
.
_tree
.
assets
(
self
.
key
)
return
assets_ids
pattern
=
'^{0}$|^{0}:'
.
format
(
self
.
key
)
return
Asset
.
objects
.
filter
(
nodes__key__regex
=
pattern
)
.
distinct
()
def
get_assets
(
self
):
from
.asset
import
Asset
if
self
.
is_
default_node
():
assets
=
Asset
.
objects
.
filter
(
Q
(
nodes
__id
=
self
.
id
)
|
Q
(
nodes__isnull
=
True
))
if
self
.
is_
org_root
():
assets
=
Asset
.
objects
.
filter
(
Q
(
nodes
=
self
)
|
Q
(
nodes__isnull
=
True
))
else
:
assets
=
Asset
.
objects
.
filter
(
id
=
self
.
assets_ids
()
)
assets
=
Asset
.
objects
.
filter
(
nodes
=
self
)
return
assets
.
distinct
()
def
get_valid_assets
(
self
):
...
...
@@ -236,6 +235,16 @@ class NodeAssetsMixin:
def
get_all_valid_assets
(
self
):
return
self
.
get_all_assets
()
.
valid
()
@classmethod
def
get_nodes_all_assets
(
cls
,
nodes_keys
):
from
.asset
import
Asset
nodes_keys
=
cls
.
clean_children_keys
(
nodes_keys
)
pattern
=
set
()
for
key
in
nodes_keys
:
pattern
.
add
(
r'^{0}$|^{0}:'
.
format
(
key
))
pattern
=
'|'
.
join
(
list
(
pattern
))
return
Asset
.
objects
.
filter
(
nodes__key__regex
=
pattern
)
class
Node
(
OrgModelMixin
,
TreeMixin
,
FamilyMixin
,
FullValueMixin
,
NodeAssetsMixin
):
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
...
...
@@ -261,22 +270,13 @@ class Node(OrgModelMixin, TreeMixin, FamilyMixin, FullValueMixin, NodeAssetsMixi
return
self
.
id
==
other
.
id
def
__gt__
(
self
,
other
):
# if self.is_root() and not other.is_root():
# return False
# elif not self.is_root() and other.is_root():
# return True
self_key
=
[
int
(
k
)
for
k
in
self
.
key
.
split
(
':'
)]
other_key
=
[
int
(
k
)
for
k
in
other
.
key
.
split
(
':'
)]
self_parent_key
=
self_key
[:
-
1
]
other_parent_key
=
other_key
[:
-
1
]
if
self_parent_key
and
other_parent_key
and
\
self_parent_key
==
other_parent_key
:
if
self_parent_key
and
self_parent_key
==
other_parent_key
:
return
self
.
value
>
other
.
value
# if len(self_parent_key) < len(other_parent_key):
# return True
# elif len(self_parent_key) > len(other_parent_key):
# return False
return
self_key
>
other_key
def
__lt__
(
self
,
other
):
...
...
@@ -310,7 +310,9 @@ class Node(OrgModelMixin, TreeMixin, FamilyMixin, FullValueMixin, NodeAssetsMixi
def
create_child
(
self
,
value
,
_id
=
None
):
with
transaction
.
atomic
():
child_key
=
self
.
get_next_child_key
()
child
=
self
.
__class__
.
objects
.
create
(
id
=
_id
,
key
=
child_key
,
value
=
value
)
child
=
self
.
__class__
.
objects
.
create
(
id
=
_id
,
key
=
child_key
,
value
=
value
)
return
child
@classmethod
...
...
@@ -318,37 +320,39 @@ class Node(OrgModelMixin, TreeMixin, FamilyMixin, FullValueMixin, NodeAssetsMixi
cls
.
refresh_tree
()
def
is_default_node
(
self
):
return
self
.
is_root
()
and
self
.
key
==
'1'
return
self
.
key
==
'1'
def
is_root
(
self
):
def
is_
org_
root
(
self
):
if
self
.
key
.
isdigit
():
return
True
else
:
return
False
@classmethod
def
create_root_node
(
cls
):
def
create_
org_
root_node
(
cls
):
# 如果使用current_org 在set_current_org时会死循环
_current
_org
=
get_current_org
()
ori
_org
=
get_current_org
()
with
transaction
.
atomic
():
if
not
_current
_org
.
is_real
():
if
not
ori
_org
.
is_real
():
return
cls
.
default_node
()
set_current_org
(
Organization
.
root
())
org_nodes_roots
=
cls
.
objects
.
filter
(
key__regex
=
r'^[0-9]+$'
)
org_nodes_roots_keys
=
org_nodes_roots
.
values_list
(
'key'
,
flat
=
True
)
or
[
'1'
]
org_nodes_roots_keys
=
org_nodes_roots
.
values_list
(
'key'
,
flat
=
True
)
if
not
org_nodes_roots_keys
:
org_nodes_roots_keys
=
[
'1'
]
key
=
max
([
int
(
k
)
for
k
in
org_nodes_roots_keys
])
key
=
str
(
key
+
1
)
if
key
!=
0
else
'2'
set_current_org
(
_current
_org
)
root
=
cls
.
objects
.
create
(
key
=
key
,
value
=
_current
_org
.
name
)
set_current_org
(
ori
_org
)
root
=
cls
.
objects
.
create
(
key
=
key
,
value
=
ori
_org
.
name
)
return
root
@classmethod
def
root
(
cls
):
def
org_
root
(
cls
):
root
=
cls
.
objects
.
filter
(
key__regex
=
r'^[0-9]+$'
)
if
root
:
return
root
[
0
]
else
:
return
cls
.
create_root_node
()
return
cls
.
create_
org_
root_node
()
@classmethod
def
default_node
(
cls
):
...
...
@@ -365,7 +369,7 @@ class Node(OrgModelMixin, TreeMixin, FamilyMixin, FullValueMixin, NodeAssetsMixi
'title'
:
name
,
'pId'
:
self
.
parent_key
,
'isParent'
:
True
,
'open'
:
self
.
is_root
(),
'open'
:
self
.
is_
org_
root
(),
'meta'
:
{
'node'
:
{
"id"
:
self
.
id
,
...
...
apps/assets/models/user.py
View file @
1fe18e80
...
...
@@ -148,9 +148,11 @@ class SystemUser(AssetUser):
return
True
,
None
def
get_all_assets
(
self
):
from
.node
import
Node
args
=
[
Q
(
systemuser
=
self
)]
pattern
=
set
()
nodes_keys
=
self
.
nodes
.
all
()
.
values_list
(
'key'
,
flat
=
True
)
nodes_keys
=
Node
.
clean_children_keys
(
nodes_keys
)
for
key
in
nodes_keys
:
pattern
.
add
(
r'^{0}$|^{0}:'
.
format
(
key
))
pattern
=
'|'
.
join
(
list
(
pattern
))
...
...
apps/assets/signals_handler.py
View file @
1fe18e80
# -*- coding: utf-8 -*-
#
from
collections
import
defaultdict
from
django.db.models.signals
import
post_save
,
m2m_changed
,
pre_delete
from
django.db.models.signals
import
(
post_save
,
m2m_changed
,
pre_delete
,
pre_save
,
pre_init
,
post_init
)
from
django.dispatch
import
receiver
from
common.utils
import
get_logger
...
...
@@ -30,6 +32,9 @@ def test_asset_conn_on_created(asset):
@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
):
"""
当资产创建时,更新硬件信息,更新可连接性
"""
if
created
:
logger
.
info
(
"Asset `{}` create signal received"
.
format
(
instance
))
...
...
@@ -37,78 +42,81 @@ def on_asset_created_or_update(sender, instance=None, created=False, **kwargs):
update_asset_hardware_info_on_created
(
instance
)
test_asset_conn_on_created
(
instance
)
# 过期节点资产数量
Node
.
refresh_nodes
()
@receiver
(
pre_delete
,
sender
=
Asset
,
dispatch_uid
=
"my_unique_identifier"
)
def
on_asset_delete
(
sender
,
instance
=
None
,
**
kwargs
):
# 过期节点资产数量
"""
当资产删除时,刷新节点,节点中存在节点和资产的关系
"""
Node
.
refresh_nodes
()
@receiver
(
post_save
,
sender
=
SystemUser
,
dispatch_uid
=
"my_unique_identifier"
)
def
on_system_user_update
(
sender
,
instance
=
None
,
created
=
True
,
**
kwargs
):
"""
当系统用户更新时,可能更新了秘钥,用户名等,这时要自动推送系统用户到资产上,
其实应该当 用户名,密码,秘钥 sudo等更新时再推送,这里偷个懒,
这里直接取了 instance.assets 因为nodes和系统用户发生变化时,会自动将nodes下的资产
关联到上面
"""
if
instance
and
not
created
:
logger
.
info
(
"System user `{}` update signal received"
.
format
(
instance
))
assets
=
instance
.
assets
.
all
()
assets
=
instance
.
assets
.
all
()
.
valid
()
push_system_user_to_assets
.
delay
(
instance
,
assets
)
# @receiver(m2m_changed, sender=SystemUser.nodes.through)
# def on_system_user_nodes_change(sender, instance=None, **kwargs):
# if instance and kwargs["action"] == "post_add":
# logger.info("System user `{}` nodes update signal received".format(instance))
# assets = set()
# nodes = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
# for node in nodes:
# assets.update(set(node.get_all_assets()))
# instance.assets.add(*tuple(assets))
#
@receiver
(
m2m_changed
,
sender
=
SystemUser
.
assets
.
through
)
@receiver
(
m2m_changed
,
sender
=
SystemUser
.
assets
.
through
,
dispatch_uid
=
"my_unique_identifier"
)
def
on_system_user_assets_change
(
sender
,
instance
=
None
,
**
kwargs
):
"""
当系统用户和资产关系发生变化时,应该重新推送系统用户到新添加的资产中
"""
if
instance
and
kwargs
[
"action"
]
==
"post_add"
:
assets
=
kwargs
[
'model'
]
.
objects
.
filter
(
pk__in
=
kwargs
[
'pk_set'
])
push_system_user_to_assets
.
delay
(
instance
,
assets
)
@receiver
(
m2m_changed
,
sender
=
Asset
.
nodes
.
through
)
def
on_asset_node_changed
(
sender
,
instance
=
None
,
**
kwargs
):
logger
.
debug
(
"Asset nodes change signal received"
)
Asset
.
expire_all_nodes_keys_cache
()
@receiver
(
m2m_changed
,
sender
=
SystemUser
.
nodes
.
through
,
dispatch_uid
=
"my_unique_identifier"
)
def
on_system_user_nodes_change
(
sender
,
instance
=
None
,
**
kwargs
):
"""
当系统用户和节点关系发生变化时,应该将节点关联到新的系统用户上
"""
if
instance
and
kwargs
[
"action"
]
==
"post_add"
:
logger
.
info
(
"System user `{}` nodes update signal received"
.
format
(
instance
))
nodes_keys
=
kwargs
[
'model'
]
.
objects
.
filter
(
pk__in
=
kwargs
[
'pk_set'
]
)
.
values_list
(
'key'
,
flat
=
True
)
assets
=
Node
.
get_nodes_all_assets
(
nodes_keys
)
instance
.
assets
.
add
(
*
tuple
(
assets
))
@receiver
(
m2m_changed
,
sender
=
Asset
.
nodes
.
through
,
dispatch_uid
=
"my_unique_identifier"
)
def
on_asset_nodes_changed
(
sender
,
instance
=
None
,
**
kwargs
):
"""
当资产的节点发生变化时,或者 当节点的资产关系发生变化时,
节点下新增的资产,添加到节点关联的系统用户中
并刷新节点
"""
if
isinstance
(
instance
,
Asset
):
# nodes = []
# if kwargs['action'] == 'pre_remove':
# nodes = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
logger
.
debug
(
"Asset nodes change signal received: {}"
.
format
(
instance
))
# 节点资产发生变化时,将资产关联到节点关联的系统用户
if
kwargs
[
'action'
]
==
'post_add'
:
nodes
=
kwargs
[
'model'
]
.
objects
.
filter
(
pk__in
=
kwargs
[
'pk_set'
])
system_users_assets
=
defaultdict
(
set
)
system_users
=
SystemUser
.
objects
.
filter
(
nodes__in
=
nodes
)
for
system_user
in
system_users
:
system_users_assets
[
system_user
]
.
update
({
instance
}
)
system_users_assets
[
system_user
]
.
add
(
instance
)
for
system_user
,
assets
in
system_users_assets
.
items
():
system_user
.
assets
.
add
(
*
tuple
(
assets
))
Node
.
refresh_nodes
()
@receiver
(
m2m_changed
,
sender
=
Asset
.
nodes
.
through
)
def
on_node_assets_changed
(
sender
,
instance
=
None
,
**
kwargs
):
if
isinstance
(
instance
,
Node
):
logger
.
debug
(
"Node assets change signal {} received"
.
format
(
instance
))
# 当节点和资产关系发生改变时,过期资产数量缓存
assets
=
kwargs
[
'model'
]
.
objects
.
filter
(
pk__in
=
kwargs
[
'pk_set'
])
if
kwargs
[
'action'
]
==
'post_add'
:
# 重新关联系统用户和资产的关系
system_users
=
SystemUser
.
objects
.
filter
(
nodes
=
instance
)
for
system_user
in
system_users
:
system_user
.
assets
.
add
(
*
tuple
(
assets
))
logger
.
debug
(
"Node assets change signal received: {}"
.
format
(
instance
))
Node
.
refresh_nodes
()
@receiver
(
post_save
,
sender
=
Node
)
def
on_node_update_or_created
(
sender
,
instance
=
None
,
created
=
False
,
**
kwargs
):
if
instance
and
not
created
:
Node
.
refresh_nodes
()
# 刷新节点
Node
.
refresh_nodes
()
@receiver
(
post_save
,
sender
=
AuthBook
)
...
...
apps/assets/views/asset.py
View file @
1fe18e80
...
...
@@ -32,7 +32,7 @@ class AssetListView(PermissionsMixin, TemplateView):
permission_classes
=
[
IsOrgAdmin
]
def
get_context_data
(
self
,
**
kwargs
):
Node
.
root
()
Node
.
org_
root
()
context
=
{
'app'
:
_
(
'Assets'
),
'action'
:
_
(
'Asset list'
),
...
...
@@ -85,7 +85,7 @@ class AssetCreateView(PermissionsMixin, FormMixin, TemplateView):
if
node_id
:
node
=
get_object_or_none
(
Node
,
id
=
node_id
)
else
:
node
=
Node
.
root
()
node
=
Node
.
org_
root
()
form
[
"nodes"
]
.
initial
=
node
return
form
...
...
apps/authentication/templates/authentication/_access_key_modal.html
View file @
1fe18e80
...
...
@@ -40,7 +40,7 @@
<script>
var
table
=
null
;
function
initTable
()
{
function
init
AccessKey
Table
()
{
var
options
=
{
ele
:
$
(
'#access_key_list_table'
),
columnDefs
:
[
...
...
@@ -93,7 +93,7 @@ function initTable() {
$
(
document
).
ready
(
function
()
{
}).
on
(
"show.bs.modal"
,
"#access_key_modal"
,
function
()
{
if
(
!
table
)
{
initTable
()
init
AccessKey
Table
()
}
}).
on
(
"click"
,
"#create-btn"
,
function
()
{
var
url
=
"{% url "
api
-
auth
:
access
-
key
-
list
" %}"
;
...
...
apps/orgs/signals_handler.py
View file @
1fe18e80
...
...
@@ -16,7 +16,7 @@ def on_org_create_or_update(sender, instance=None, created=False, **kwargs):
if
instance
:
old_org
=
get_current_org
()
set_current_org
(
instance
)
node_root
=
Node
.
root
()
node_root
=
Node
.
org_
root
()
if
node_root
.
value
!=
instance
.
name
:
node_root
.
value
=
instance
.
name
node_root
.
save
()
...
...
apps/perms/models/asset_permission.py
View file @
1fe18e80
...
...
@@ -97,6 +97,7 @@ class AssetPermission(BasePermission):
args
=
[
Q
(
granted_by_permissions
=
self
)]
pattern
=
set
()
nodes_keys
=
self
.
nodes
.
all
()
.
values_list
(
'key'
,
flat
=
True
)
nodes_keys
=
Node
.
clean_children_keys
(
nodes_keys
)
for
key
in
nodes_keys
:
pattern
.
add
(
r'^{0}$|^{0}:'
.
format
(
key
))
pattern
=
'|'
.
join
(
list
(
pattern
))
...
...
apps/perms/signals_handler.py
View file @
1fe18e80
...
...
@@ -2,24 +2,15 @@
#
from
django.db.models.signals
import
m2m_changed
,
post_save
,
post_delete
from
django.dispatch
import
receiver
from
django.db
import
transaction
from
common.utils
import
get_logger
from
common.decorator
import
on_transaction_commit
from
.models
import
AssetPermission
logger
=
get_logger
(
__file__
)
def
on_transaction_commit
(
func
):
"""
如果不调用on_commit, 对象创建时添加多对多字段值失败
"""
def
inner
(
*
args
,
**
kwargs
):
transaction
.
on_commit
(
lambda
:
func
(
*
args
,
**
kwargs
))
return
inner
@receiver
(
post_save
,
sender
=
AssetPermission
,
dispatch_uid
=
"my_unique_identifier"
)
@on_transaction_commit
def
on_permission_created
(
sender
,
instance
=
None
,
created
=
False
,
**
kwargs
):
...
...
apps/perms/utils/asset_permission.py
View file @
1fe18e80
# coding: utf-8
import
re
from
collections
import
defaultdict
from
functools
import
reduce
...
...
@@ -250,6 +249,7 @@ class AssetPermissionUtilV2:
return
system_users_actions
def
get_permissions_nodes_and_assets
(
self
):
from
assets.models
import
Node
permissions
=
self
.
permissions
.
values_list
(
'assets'
,
'nodes__key'
)
.
distinct
()
nodes_keys
=
set
()
assets_ids
=
set
()
...
...
@@ -258,7 +258,7 @@ class AssetPermissionUtilV2:
assets_ids
.
add
(
asset_id
)
if
node_key
:
nodes_keys
.
add
(
node_key
)
nodes_keys
=
self
.
clean_nodes
_keys
(
nodes_keys
)
nodes_keys
=
Node
.
clean_children
_keys
(
nodes_keys
)
return
nodes_keys
,
assets_ids
@staticmethod
...
...
@@ -297,20 +297,6 @@ class AssetPermissionUtilV2:
queryset
=
Asset
.
objects
.
filter
(
id__in
=
assets_ids
)
return
queryset
.
valid
()
.
distinct
()
@staticmethod
def
clean_nodes_keys
(
nodes_keys
):
nodes_keys
=
sorted
(
list
(
nodes_keys
),
key
=
lambda
x
:
(
len
(
x
),
x
))
nodes_keys_clean
=
[]
for
key
in
nodes_keys
[::
-
1
]:
found
=
False
for
k
in
nodes_keys
:
if
key
.
startswith
(
k
+
':'
):
found
=
True
break
if
not
found
:
nodes_keys_clean
.
append
(
key
)
return
nodes_keys_clean
def
get_nodes
(
self
):
return
[
n
.
identifier
for
n
in
self
.
user_tree
.
all_nodes_itr
()]
...
...
@@ -357,7 +343,7 @@ class ParserNode:
'title'
:
name
,
'pId'
:
node
.
parent_key
,
'isParent'
:
True
,
'open'
:
node
.
is_root
(),
'open'
:
node
.
is_
org_
root
(),
'meta'
:
{
'node'
:
{
"id"
:
node
.
id
,
...
...
apps/perms/views/asset_permission.py
View file @
1fe18e80
...
...
@@ -51,7 +51,8 @@ class AssetPermissionCreateView(PermissionsMixin, CreateView):
if
nodes_id
:
nodes_id
=
nodes_id
.
split
(
","
)
nodes
=
Node
.
objects
.
filter
(
id__in
=
nodes_id
)
.
exclude
(
id
=
Node
.
root
()
.
id
)
nodes
=
Node
.
objects
.
filter
(
id__in
=
nodes_id
)
\
.
exclude
(
id
=
Node
.
org_root
()
.
id
)
form
[
'nodes'
]
.
initial
=
nodes
if
assets_id
:
assets_id
=
assets_id
.
split
(
","
)
...
...
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