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
ae690050
Commit
ae690050
authored
5 years ago
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Stash
parent
8f699fa3
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
236 additions
and
205 deletions
+236
-205
system_user.py
apps/assets/serializers/system_user.py
+1
-6
utils.py
apps/assets/utils.py
+17
-9
asset_permission.py
apps/perms/api/asset_permission.py
+2
-1
user_permission.py
apps/perms/api/user_permission.py
+7
-2
asset_permission.py
apps/perms/forms/asset_permission.py
+2
-2
0006_auto_20190628_1921.py
apps/perms/migrations/0006_auto_20190628_1921.py
+1
-1
0007_remove_assetpermission_actions.py
apps/perms/migrations/0007_remove_assetpermission_actions.py
+5
-0
asset_permission.py
apps/perms/models/asset_permission.py
+27
-20
asset_permission.py
apps/perms/serializers/asset_permission.py
+2
-2
asset_permission_list.html
apps/perms/templates/perms/asset_permission_list.html
+3
-3
asset_permission.py
apps/perms/utils/asset_permission.py
+169
-123
test_asset_permission.py
apps/perms/utils/test_asset_permission.py
+0
-36
No files found.
apps/assets/serializers/system_user.py
View file @
ae690050
...
@@ -50,19 +50,14 @@ class AssetSystemUserSerializer(serializers.ModelSerializer):
...
@@ -50,19 +50,14 @@ class AssetSystemUserSerializer(serializers.ModelSerializer):
"""
"""
查看授权的资产系统用户的数据结构,这个和AssetSerializer不同,字段少
查看授权的资产系统用户的数据结构,这个和AssetSerializer不同,字段少
"""
"""
actions
=
serializers
.
SerializerMethodField
()
class
Meta
:
class
Meta
:
model
=
SystemUser
model
=
SystemUser
fields
=
(
fields
=
(
'id'
,
'name'
,
'username'
,
'priority'
,
'id'
,
'name'
,
'username'
,
'priority'
,
'protocol'
,
'comment'
,
'login_mode'
,
'actions'
,
'protocol'
,
'comment'
,
'login_mode'
,
)
)
@staticmethod
def
get_actions
(
obj
):
return
[
action
.
name
for
action
in
obj
.
actions
]
class
SystemUserSimpleSerializer
(
serializers
.
ModelSerializer
):
class
SystemUserSimpleSerializer
(
serializers
.
ModelSerializer
):
"""
"""
...
...
This diff is collapsed.
Click to expand it.
apps/assets/utils.py
View file @
ae690050
...
@@ -54,17 +54,19 @@ class NodeUtil:
...
@@ -54,17 +54,19 @@ class NodeUtil:
def
sorted_by
(
node
):
def
sorted_by
(
node
):
return
[
int
(
i
)
for
i
in
node
.
key
.
split
(
':'
)]
return
[
int
(
i
)
for
i
in
node
.
key
.
split
(
':'
)]
def
get_
all_nodes
(
self
):
def
get_
queryset
(
self
):
all_nodes
=
Node
.
objects
.
all
()
all_nodes
=
Node
.
objects
.
all
()
if
self
.
with_assets_amount
:
if
self
.
with_assets_amount
:
now
=
time
.
time
()
all_nodes
=
all_nodes
.
prefetch_related
(
all_nodes
=
all_nodes
.
prefetch_related
(
Prefetch
(
'assets'
,
queryset
=
Asset
.
objects
.
all
()
.
only
(
'id'
))
Prefetch
(
'assets'
,
queryset
=
Asset
.
objects
.
all
()
.
only
(
'id'
))
)
)
all_nodes
=
list
(
all_nodes
)
all_nodes
=
list
(
all_nodes
)
for
node
in
all_nodes
:
for
node
in
all_nodes
:
node
.
_assets
=
set
(
node
.
assets
.
all
())
node
.
_assets
=
set
(
node
.
assets
.
all
())
all_nodes
=
sorted
(
all_nodes
,
key
=
self
.
sorted_by
)
return
all_nodes
def
get_all_nodes
(
self
):
all_nodes
=
sorted
(
self
.
get_queryset
(),
key
=
self
.
sorted_by
)
guarder
=
Node
(
key
=
''
,
value
=
'Guarder'
)
guarder
=
Node
(
key
=
''
,
value
=
'Guarder'
)
guarder
.
_assets
=
[]
guarder
.
_assets
=
[]
...
@@ -119,11 +121,11 @@ class NodeUtil:
...
@@ -119,11 +121,11 @@ class NodeUtil:
def
get_nodes_by_queryset
(
self
,
queryset
):
def
get_nodes_by_queryset
(
self
,
queryset
):
nodes
=
[]
nodes
=
[]
for
n
in
queryset
:
for
n
in
queryset
:
node
=
self
.
_nodes
.
get
(
n
.
key
)
node
=
self
.
get_node_by_key
(
n
.
key
)
if
not
node
:
if
not
node
:
continue
continue
nodes
.
append
(
node
s
)
nodes
.
append
(
node
)
return
[
self
]
return
nodes
def
get_node_by_key
(
self
,
key
):
def
get_node_by_key
(
self
,
key
):
return
self
.
_nodes
.
get
(
key
)
return
self
.
_nodes
.
get
(
key
)
...
@@ -156,11 +158,17 @@ class NodeUtil:
...
@@ -156,11 +158,17 @@ class NodeUtil:
tree_nodes
.
add
(
node
)
tree_nodes
.
add
(
node
)
if
with_children
:
if
with_children
:
tree_nodes
.
update
(
node
.
_children
)
tree_nodes
.
update
(
node
.
_children
)
for
n
in
tree_nodes
:
delattr
(
n
,
'_children'
)
delattr
(
n
,
'_parents'
)
return
list
(
tree_nodes
)
return
list
(
tree_nodes
)
def
get_nodes_parents
(
self
,
nodes
,
with_self
=
True
):
parents
=
set
()
for
n
in
nodes
:
node
=
self
.
get_node_by_key
(
n
.
key
)
parents
.
update
(
set
(
node
.
_parents
))
if
with_self
:
parents
.
add
(
node
)
return
parents
def
test_node_tree
():
def
test_node_tree
():
tree
=
NodeUtil
()
tree
=
NodeUtil
()
...
...
This diff is collapsed.
Click to expand it.
apps/perms/api/asset_permission.py
View file @
ae690050
...
@@ -35,7 +35,8 @@ class AssetPermissionViewSet(viewsets.ModelViewSet):
...
@@ -35,7 +35,8 @@ class AssetPermissionViewSet(viewsets.ModelViewSet):
permission_classes
=
(
IsOrgAdmin
,)
permission_classes
=
(
IsOrgAdmin
,)
def
get_serializer_class
(
self
):
def
get_serializer_class
(
self
):
if
self
.
action
in
(
"list"
,
'retrieve'
):
if
self
.
action
in
(
"list"
,
'retrieve'
)
and
\
self
.
request
.
query_params
.
get
(
"display"
):
return
serializers
.
AssetPermissionListSerializer
return
serializers
.
AssetPermissionListSerializer
return
self
.
serializer_class
return
self
.
serializer_class
...
...
This diff is collapsed.
Click to expand it.
apps/perms/api/user_permission.py
View file @
ae690050
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
#
#
import
time
from
hashlib
import
md5
from
hashlib
import
md5
from
django.core.cache
import
cache
from
django.core.cache
import
cache
from
django.conf
import
settings
from
django.conf
import
settings
...
@@ -261,14 +261,19 @@ class UserGrantedNodesWithAssetsAsTreeApi(UserPermissionCacheMixin, ListAPIView)
...
@@ -261,14 +261,19 @@ class UserGrantedNodesWithAssetsAsTreeApi(UserPermissionCacheMixin, ListAPIView)
nodes
=
util
.
get_nodes_with_assets
()
nodes
=
util
.
get_nodes_with_assets
()
print
(
"22222222222222"
)
print
(
"22222222222222"
)
for
node
,
assets
in
nodes
.
items
():
for
node
,
assets
in
nodes
.
items
():
now
=
time
.
time
()
print
(
"Parse to node"
)
data
=
parse_node_to_tree_node
(
node
)
data
=
parse_node_to_tree_node
(
node
)
print
(
"parse to node end, using: {0:.2f}"
.
format
(
time
.
time
()
-
now
))
queryset
.
append
(
data
)
queryset
.
append
(
data
)
if
not
self
.
show_assets
:
if
not
self
.
show_assets
:
continue
continue
for
asset
,
system_users
in
assets
.
items
():
for
asset
,
system_users
in
assets
.
items
():
now1
=
time
.
time
()
print
(
"parse to asset"
)
data
=
parse_asset_to_tree_node
(
node
,
asset
,
system_users
)
data
=
parse_asset_to_tree_node
(
node
,
asset
,
system_users
)
print
(
"parse to asset end, using: {0:.2f}"
.
format
(
time
.
time
()
-
now1
))
queryset
.
append
(
data
)
queryset
.
append
(
data
)
queryset
=
sorted
(
queryset
)
return
queryset
return
queryset
...
...
This diff is collapsed.
Click to expand it.
apps/perms/forms/asset_permission.py
View file @
ae690050
...
@@ -74,13 +74,13 @@ class AssetPermissionForm(OrgModelForm):
...
@@ -74,13 +74,13 @@ class AssetPermissionForm(OrgModelForm):
'system_users'
:
forms
.
SelectMultiple
(
'system_users'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'System user'
)}
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'System user'
)}
),
),
'action'
:
forms
.
CheckboxSelectMultiple
()
'action
s
'
:
forms
.
CheckboxSelectMultiple
()
}
}
labels
=
{
labels
=
{
'nodes'
:
_
(
"Node"
),
'nodes'
:
_
(
"Node"
),
}
}
help_texts
=
{
help_texts
=
{
'action'
:
_
(
'Tips: The RDP protocol does not support separate '
'action
s
'
:
_
(
'Tips: The RDP protocol does not support separate '
'controls for uploading or downloading files'
)
'controls for uploading or downloading files'
)
}
}
...
...
This diff is collapsed.
Click to expand it.
apps/perms/migrations/0006_auto_20190628_1921.py
View file @
ae690050
...
@@ -36,7 +36,7 @@ class Migration(migrations.Migration):
...
@@ -36,7 +36,7 @@ class Migration(migrations.Migration):
migrations
.
AddField
(
migrations
.
AddField
(
model_name
=
'assetpermission'
,
model_name
=
'assetpermission'
,
name
=
'action'
,
name
=
'action'
,
field
=
models
.
IntegerField
(
choices
=
[(
255
,
'All'
),
(
1
,
'Connect'
),
(
2
,
'Upload file'
),
(
5
,
'Upload download'
),
(
4
,
'Download file'
)],
default
=
255
,
verbose_name
=
'Action
'
),
field
=
models
.
IntegerField
(
choices
=
[(
255
,
'All'
),
(
1
,
'Connect'
),
(
2
,
'Upload file'
),
(
4
,
'Download file'
),
(
6
,
'Upload download'
)],
default
=
255
,
verbose_name
=
'Actions
'
),
),
),
migrations
.
RunPython
(
migrate_old_actions
),
migrations
.
RunPython
(
migrate_old_actions
),
]
]
This diff is collapsed.
Click to expand it.
apps/perms/migrations/0007_remove_assetpermission_actions.py
View file @
ae690050
...
@@ -14,4 +14,9 @@ class Migration(migrations.Migration):
...
@@ -14,4 +14,9 @@ class Migration(migrations.Migration):
model_name
=
'assetpermission'
,
model_name
=
'assetpermission'
,
name
=
'actions'
,
name
=
'actions'
,
),
),
migrations
.
RenameField
(
model_name
=
'assetpermission'
,
old_name
=
'action'
,
new_name
=
'actions'
,
),
]
]
This diff is collapsed.
Click to expand it.
apps/perms/models/asset_permission.py
View file @
ae690050
...
@@ -39,39 +39,46 @@ class ActionFlag:
...
@@ -39,39 +39,46 @@ class ActionFlag:
UPLOAD
=
0
b00000010
UPLOAD
=
0
b00000010
DOWNLOAD
=
0
b00000100
DOWNLOAD
=
0
b00000100
UPDOWNLOAD
=
UPLOAD
|
DOWNLOAD
UPDOWNLOAD
=
UPLOAD
|
DOWNLOAD
CONNECT_UPLOADOWN
=
CONNECT
|
UPDOWNLOAD
ALL
=
0
b11111111
ALL
=
0
b11111111
NAME_MAP
=
{
"connect"
:
CONNECT
,
"upload"
:
UPLOAD
,
"download"
:
DOWNLOAD
,
"updownload"
:
UPDOWNLOAD
,
"all"
:
ALL
,
}
CHOICES
=
(
DB_
CHOICES
=
(
(
ALL
,
_
(
'All'
)),
(
ALL
,
_
(
'All'
)),
(
CONNECT
,
_
(
'Connect'
)),
(
CONNECT
,
_
(
'Connect'
)),
(
UPDOWNLOAD
,
_
(
"Upload download"
)),
(
UPLOAD
,
_
(
'Upload file'
)),
(
UPLOAD
,
_
(
'Upload file'
)),
(
DOWNLOAD
,
_
(
'Download file'
)),
(
DOWNLOAD
,
_
(
'Download file'
)),
(
UPDOWNLOAD
,
_
(
"Upload download"
)),
)
)
NAME_MAP
=
{
ALL
:
"all"
,
CONNECT
:
"connect"
,
UPLOAD
:
"upload_file"
,
DOWNLOAD
:
"download_file"
,
UPDOWNLOAD
:
"updownload"
,
}
NAME_MAP_REVERSE
=
dict
({
v
:
k
for
k
,
v
in
NAME_MAP
.
items
()})
CHOICES
=
[]
for
i
,
j
in
DB_CHOICES
:
CHOICES
.
append
((
NAME_MAP
[
i
],
j
))
@classmethod
@classmethod
def
value_to_choices
(
cls
,
value
):
def
value_to_choices
(
cls
,
value
):
value
=
int
(
value
)
value
=
int
(
value
)
if
value
==
cls
.
ALL
:
choices
=
[
cls
.
NAME_MAP
[
i
]
for
i
,
j
in
cls
.
DB_CHOICES
if
value
&
i
==
i
]
return
[
cls
.
ALL
]
return
choices
elif
value
==
cls
.
UPDOWNLOAD
:
return
[
cls
.
UPDOWNLOAD
]
elif
value
==
cls
.
CONNECT_UPLOADOWN
:
return
[
cls
.
CONNECT
,
cls
.
UPDOWNLOAD
]
else
:
return
[
i
for
i
in
dict
(
cls
.
CHOICES
)
if
i
==
i
&
int
(
value
)]
@classmethod
@classmethod
def
choices_to_value
(
cls
,
value
):
def
choices_to_value
(
cls
,
value
):
return
reduce
(
lambda
x
,
y
:
int
(
x
)
|
int
(
y
),
value
)
def
to_choices
(
x
,
y
):
x
=
cls
.
NAME_MAP_REVERSE
.
get
(
x
,
0
)
y
=
cls
.
NAME_MAP_REVERSE
.
get
(
y
,
0
)
return
x
|
y
return
reduce
(
to_choices
,
value
)
@classmethod
def
choices
(
cls
):
return
[(
cls
.
NAME_MAP
[
i
],
j
)
for
i
,
j
in
cls
.
DB_CHOICES
]
class
AssetPermission
(
BasePermission
):
class
AssetPermission
(
BasePermission
):
...
@@ -79,7 +86,7 @@ class AssetPermission(BasePermission):
...
@@ -79,7 +86,7 @@ class AssetPermission(BasePermission):
nodes
=
models
.
ManyToManyField
(
'assets.Node'
,
related_name
=
'granted_by_permissions'
,
blank
=
True
,
verbose_name
=
_
(
"Nodes"
))
nodes
=
models
.
ManyToManyField
(
'assets.Node'
,
related_name
=
'granted_by_permissions'
,
blank
=
True
,
verbose_name
=
_
(
"Nodes"
))
system_users
=
models
.
ManyToManyField
(
'assets.SystemUser'
,
related_name
=
'granted_by_permissions'
,
verbose_name
=
_
(
"System user"
))
system_users
=
models
.
ManyToManyField
(
'assets.SystemUser'
,
related_name
=
'granted_by_permissions'
,
verbose_name
=
_
(
"System user"
))
# actions = models.ManyToManyField(Action, related_name='permissions', blank=True, verbose_name=_('Action'))
# actions = models.ManyToManyField(Action, related_name='permissions', blank=True, verbose_name=_('Action'))
action
=
models
.
IntegerField
(
choices
=
ActionFlag
.
CHOICES
,
default
=
ActionFlag
.
ALL
,
verbose_name
=
_
(
"Action
"
))
action
s
=
models
.
IntegerField
(
choices
=
ActionFlag
.
DB_CHOICES
,
default
=
ActionFlag
.
ALL
,
verbose_name
=
_
(
"Actions
"
))
class
Meta
:
class
Meta
:
unique_together
=
[(
'org_id'
,
'name'
)]
unique_together
=
[(
'org_id'
,
'name'
)]
...
...
This diff is collapsed.
Click to expand it.
apps/perms/serializers/asset_permission.py
View file @
ae690050
...
@@ -38,7 +38,7 @@ class ActionDisplayField(ActionField):
...
@@ -38,7 +38,7 @@ class ActionDisplayField(ActionField):
class
AssetPermissionCreateUpdateSerializer
(
BulkOrgResourceModelSerializer
):
class
AssetPermissionCreateUpdateSerializer
(
BulkOrgResourceModelSerializer
):
action
=
ActionField
()
action
s
=
ActionField
()
class
Meta
:
class
Meta
:
model
=
AssetPermission
model
=
AssetPermission
...
@@ -51,7 +51,7 @@ class AssetPermissionListSerializer(BulkOrgResourceModelSerializer):
...
@@ -51,7 +51,7 @@ class AssetPermissionListSerializer(BulkOrgResourceModelSerializer):
assets
=
StringManyToManyField
(
many
=
True
,
read_only
=
True
)
assets
=
StringManyToManyField
(
many
=
True
,
read_only
=
True
)
nodes
=
StringManyToManyField
(
many
=
True
,
read_only
=
True
)
nodes
=
StringManyToManyField
(
many
=
True
,
read_only
=
True
)
system_users
=
StringManyToManyField
(
many
=
True
,
read_only
=
True
)
system_users
=
StringManyToManyField
(
many
=
True
,
read_only
=
True
)
action
=
ActionDisplayField
()
action
s
=
ActionDisplayField
()
is_valid
=
serializers
.
BooleanField
()
is_valid
=
serializers
.
BooleanField
()
is_expired
=
serializers
.
BooleanField
()
is_expired
=
serializers
.
BooleanField
()
...
...
This diff is collapsed.
Click to expand it.
apps/perms/templates/perms/asset_permission_list.html
View file @
ae690050
...
@@ -122,8 +122,8 @@ function format(d) {
...
@@ -122,8 +122,8 @@ function format(d) {
if
(
d
.
system_users
.
length
>
0
)
{
if
(
d
.
system_users
.
length
>
0
)
{
data
+=
makeLabel
([
"{% trans 'System user' %}"
,
d
.
system_users
.
join
(
", "
)])
data
+=
makeLabel
([
"{% trans 'System user' %}"
,
d
.
system_users
.
join
(
", "
)])
}
}
if
(
d
.
action
.
length
>
0
)
{
if
(
d
.
action
s
.
length
>
0
)
{
data
+=
makeLabel
([
"{% trans 'Action' %}"
,
d
.
action
.
join
(
", "
)])
data
+=
makeLabel
([
"{% trans 'Action' %}"
,
d
.
action
s
.
join
(
", "
)])
}
}
return
data
return
data
}
}
...
@@ -180,7 +180,7 @@ function initTable() {
...
@@ -180,7 +180,7 @@ function initTable() {
$
(
td
).
html
(
update_btn
+
del_btn
);
$
(
td
).
html
(
update_btn
+
del_btn
);
}}
}}
],
],
ajax_url
:
'{% url "api-perms:asset-permission-list" %}'
,
ajax_url
:
'{% url "api-perms:asset-permission-list" %}
?display=1
'
,
columns
:
[
columns
:
[
{
data
:
"id"
},
{
data
:
"name"
},
{
data
:
"users"
},
{
data
:
"id"
},
{
data
:
"name"
},
{
data
:
"users"
},
{
data
:
"user_groups"
},
{
data
:
"assets"
},
{
data
:
"user_groups"
},
{
data
:
"assets"
},
...
...
This diff is collapsed.
Click to expand it.
apps/perms/utils/asset_permission.py
View file @
ae690050
...
@@ -17,8 +17,8 @@ from orgs.utils import set_to_root_org
...
@@ -17,8 +17,8 @@ from orgs.utils import set_to_root_org
from
common.utils
import
get_logger
from
common.utils
import
get_logger
from
common.tree
import
TreeNode
from
common.tree
import
TreeNode
from
..
import
const
from
..
import
const
from
..models
import
AssetPermission
,
Action
from
..models
import
AssetPermission
,
Action
,
ActionFlag
from
..hands
import
Node
from
..hands
import
Node
,
Asset
from
assets.utils
import
NodeUtil
from
assets.utils
import
NodeUtil
logger
=
get_logger
(
__file__
)
logger
=
get_logger
(
__file__
)
...
@@ -31,17 +31,57 @@ __all__ = [
...
@@ -31,17 +31,57 @@ __all__ = [
]
]
class
TreeNodeCounter
(
NodeUtil
):
def
__init__
(
self
,
nodes
):
self
.
__nodes
=
nodes
super
()
.
__init__
(
with_assets_amount
=
True
)
def
get_queryset
(
self
):
return
self
.
__nodes
def
timeit
(
func
):
def
wrapper
(
*
args
,
**
kwargs
):
logger
.
debug
(
"Start call: {}"
.
format
(
func
.
__name__
))
now
=
time
.
time
()
result
=
func
(
*
args
,
**
kwargs
)
using
=
time
.
time
()
-
now
logger
.
debug
(
"Call {} end, using: {:.2}s"
.
format
(
func
.
__name__
,
using
))
return
result
return
wrapper
class
GenerateTree
:
class
GenerateTree
:
def
__init__
(
self
):
def
__init__
(
self
):
"""
"""
nodes: {"node_instance": {
nodes = {
"asset_instance": set("system_user")
"<node1>": {
"system_users": {
"system_user": action,
"system_user2": action,
},
"assets": set([<asset_instance>]),
}
}
assets = {
"<asset_instance2>": {
"system_user": action,
"system_user2": action,
},
}
}
"""
"""
self
.
node_util
=
NodeUtil
()
self
.
_node_util
=
None
self
.
nodes
=
defaultdict
(
dict
)
self
.
nodes
=
defaultdict
(
lambda
:
{
"system_users"
:
defaultdict
(
int
),
"assets"
:
set
(),
"assets_amount"
:
0
})
self
.
assets
=
defaultdict
(
lambda
:
defaultdict
(
int
))
self
.
_root_node
=
None
self
.
_root_node
=
None
self
.
_ungroup_node
=
None
self
.
_ungroup_node
=
None
self
.
_nodes_with_assets
=
None
@property
def
node_util
(
self
):
if
not
self
.
_node_util
:
self
.
_node_util
=
NodeUtil
()
return
self
.
_node_util
@property
@property
def
root_node
(
self
):
def
root_node
(
self
):
...
@@ -66,35 +106,79 @@ class GenerateTree:
...
@@ -66,35 +106,79 @@ class GenerateTree:
node_key
=
'0:0'
node_key
=
'0:0'
node_value
=
_
(
"Default"
)
node_value
=
_
(
"Default"
)
node
=
Node
(
id
=
node_id
,
key
=
node_key
,
value
=
node_value
)
node
=
Node
(
id
=
node_id
,
key
=
node_key
,
value
=
node_value
)
self
.
add_node
(
node
)
self
.
add_node
(
node
,
{}
)
self
.
_ungroup_node
=
node
self
.
_ungroup_node
=
node
return
node
return
node
def
add_asset
(
self
,
asset
,
system_users
):
@timeit
def
add_assets_without_system_users
(
self
,
assets
):
for
asset
in
assets
:
self
.
add_asset
(
asset
,
{})
@timeit
def
add_assets
(
self
,
assets
):
for
asset
,
system_users
in
assets
.
items
():
self
.
add_asset
(
asset
,
system_users
)
@timeit
def
add_asset
(
self
,
asset
,
system_users
=
None
):
nodes
=
asset
.
nodes
.
all
()
nodes
=
asset
.
nodes
.
all
()
for
node
in
nodes
:
nodes
=
self
.
node_util
.
get_nodes_by_queryset
(
nodes
)
if
node
in
self
.
nodes
:
if
not
system_users
:
self
.
nodes
[
node
][
asset
]
.
update
(
system_users
)
system_users
=
defaultdict
(
int
)
else
:
else
:
self
.
nodes
[
self
.
ungrouped_node
][
asset
]
.
update
(
system_users
)
system_users
=
{
k
:
v
for
k
,
v
in
system_users
.
items
()}
_system_users
=
self
.
assets
[
asset
]
def
get_nodes
(
self
):
for
system_user
,
action
in
_system_users
.
items
():
for
node
in
self
.
nodes
:
system_users
[
system_user
]
|=
action
assets
=
set
(
self
.
nodes
.
get
(
node
)
.
keys
())
for
n
in
self
.
nodes
.
keys
():
# 获取父节点们
if
n
.
key
.
startswith
(
node
.
key
+
':'
):
parents
=
self
.
node_util
.
get_nodes_parents
(
nodes
,
with_self
=
True
)
assets
.
update
(
set
(
self
.
nodes
[
n
]
.
keys
()))
for
node
in
parents
:
node
.
assets_amount
=
len
(
assets
)
_system_users
=
self
.
nodes
[
node
][
"system_users"
]
return
self
.
nodes
self
.
nodes
[
node
][
"assets_amount"
]
+=
1
for
system_user
,
action
in
_system_users
.
items
():
def
add_node
(
self
,
node
):
system_users
[
system_user
]
|=
action
self
.
nodes
[
node
]
=
defaultdict
(
set
)
# 过滤系统用户的协议
system_users
=
{
s
:
v
for
s
,
v
in
system_users
.
items
()
if
asset
.
has_protocol
(
s
.
protocol
)}
self
.
assets
[
asset
]
=
system_users
in_nodes
=
set
(
self
.
nodes
.
keys
())
&
set
(
nodes
)
if
not
in_nodes
:
self
.
nodes
[
self
.
ungrouped_node
][
"assets_amount"
]
+=
1
self
.
nodes
[
self
.
ungrouped_node
][
"assets"
]
.
add
(
system_users
)
return
for
node
in
in_nodes
:
self
.
nodes
[
node
][
"assets"
]
.
add
(
asset
)
def
add_node
(
self
,
node
,
system_users
=
None
):
if
not
system_users
:
system_users
=
defaultdict
(
int
)
self
.
nodes
[
node
][
"system_users"
]
=
system_users
# 添加树节点
# 添加树节点
@timeit
def
add_nodes
(
self
,
nodes
):
def
add_nodes
(
self
,
nodes
):
need_nodes
=
self
.
node_util
.
get_family
(
nodes
,
with_children
=
True
)
_nodes
=
nodes
.
keys
()
for
node
in
need_nodes
:
family
=
self
.
node_util
.
get_family
(
_nodes
,
with_children
=
True
)
self
.
add_node
(
node
)
for
node
in
family
:
self
.
add_node
(
node
,
nodes
.
get
(
node
,
{}))
def
get_assets
(
self
):
return
dict
(
self
.
assets
)
@timeit
def
get_nodes_with_assets
(
self
):
if
self
.
_nodes_with_assets
:
return
self
.
_nodes_with_assets
nodes
=
{}
for
node
,
values
in
self
.
nodes
.
items
():
node
.
_assets_amount
=
values
[
"assets_amount"
]
nodes
[
node
]
=
{
asset
:
self
.
assets
.
get
(
asset
,
{})
for
asset
in
values
[
"assets"
]}
self
.
_nodes_with_assets
=
nodes
return
dict
(
nodes
)
def
get_user_permissions
(
user
,
include_group
=
True
):
def
get_user_permissions
(
user
,
include_group
=
True
):
...
@@ -131,17 +215,6 @@ def get_system_user_permissions(system_user):
...
@@ -131,17 +215,6 @@ def get_system_user_permissions(system_user):
)
)
def
timeit
(
func
):
def
wrapper
(
*
args
,
**
kwargs
):
logger
.
debug
(
"Start call: {}"
.
format
(
func
.
__name__
))
now
=
time
.
time
()
result
=
func
(
*
args
,
**
kwargs
)
using
=
time
.
time
()
-
now
logger
.
debug
(
"Call {} end, using: {:.2}"
.
format
(
func
.
__name__
,
using
))
return
result
return
wrapper
class
AssetPermissionCacheMixin
:
class
AssetPermissionCacheMixin
:
CACHE_KEY_PREFIX
=
'_ASSET_PERM_CACHE_'
CACHE_KEY_PREFIX
=
'_ASSET_PERM_CACHE_'
CACHE_META_KEY_PREFIX
=
'_ASSET_PERM_META_KEY_'
CACHE_META_KEY_PREFIX
=
'_ASSET_PERM_META_KEY_'
...
@@ -216,6 +289,16 @@ class AssetPermissionCacheMixin:
...
@@ -216,6 +289,16 @@ class AssetPermissionCacheMixin:
cached
=
cache
.
get
(
self
.
system_key
)
cached
=
cache
.
get
(
self
.
system_key
)
return
cached
return
cached
def
get_assets
(
self
):
if
self
.
_is_not_using_cache
():
return
self
.
get_assets_from_cache
()
elif
self
.
_is_refresh_cache
():
self
.
expire_cache
()
return
self
.
get_assets_from_cache
()
else
:
self
.
expire_cache
()
return
self
.
get_assets_without_cache
()
def
get_system_users
(
self
):
def
get_system_users
(
self
):
if
self
.
_is_using_cache
():
if
self
.
_is_using_cache
():
return
self
.
get_system_user_from_cache
()
return
self
.
get_system_user_from_cache
()
...
@@ -282,57 +365,6 @@ class AssetPermissionCacheMixin:
...
@@ -282,57 +365,6 @@ class AssetPermissionCacheMixin:
cache
.
delete_pattern
(
key
)
cache
.
delete_pattern
(
key
)
class
FlatPermissionQueryset
(
set
):
def
add_many
(
self
,
assets_or_nodes
,
system_users
,
action
,
rtp
=
"asset"
):
print
(
"Add many: {}-{}-{}"
.
format
(
len
(
assets_or_nodes
),
len
(
system_users
),
action
))
if
not
any
([
assets_or_nodes
,
system_users
,
action
]):
return
iterable
=
itertools
.
product
(
assets_or_nodes
,
system_users
,
[
action
])
for
source
,
sysuser
,
action
in
iterable
:
permission
=
FlatPermission
(
source
,
sysuser
,
action
,
rtp
=
rtp
)
print
(
"ADDDDDDDDDDDDDDDd"
)
self
.
add
(
permission
)
def
group_by_resource
(
self
):
resources
=
defaultdict
(
lambda
:
defaultdict
(
int
))
for
i
in
self
:
resources
[
i
.
resource
][
i
.
system_user
]
|=
i
.
action
return
resources
class
FlatPermission
:
def
__init__
(
self
,
assets_or_node
,
system_user
,
action
,
rtp
=
"asset"
):
self
.
id
=
"{}_{}_{}"
.
format
(
assets_or_node
.
id
,
system_user
.
id
,
action
)
self
.
resource
=
assets_or_node
self
.
resource_type
=
rtp
self
.
system_user
=
system_user
self
.
action
=
action
def
__eq__
(
self
,
other
):
if
self
.
id
==
other
.
id
:
return
True
# 资产不同
if
self
.
resource_type
==
"asset"
and
self
.
id
!=
other
.
id
:
return
False
# 不是子节点
elif
self
.
resource_type
==
"node"
and
not
other
.
resource
.
key
.
startswith
(
self
.
resource
.
key
):
return
False
# 系统用户优先级大于后者,则相同
if
self
.
system_user
.
priority
>
self
.
system_user
.
priority
:
return
True
# 如果系统用户不同,则不同
elif
self
.
system_user
!=
other
.
system_user
:
return
False
# 如果action为与后的结果则相同
if
self
.
action
==
self
.
action
|
other
.
action
:
return
True
return
False
def
__hash__
(
self
):
return
hash
(
self
.
id
)
class
AssetPermissionUtil
(
AssetPermissionCacheMixin
):
class
AssetPermissionUtil
(
AssetPermissionCacheMixin
):
get_permissions_map
=
{
get_permissions_map
=
{
"User"
:
get_user_permissions
,
"User"
:
get_user_permissions
,
...
@@ -353,6 +385,7 @@ class AssetPermissionUtil(AssetPermissionCacheMixin):
...
@@ -353,6 +385,7 @@ class AssetPermissionUtil(AssetPermissionCacheMixin):
self
.
tree
=
GenerateTree
()
self
.
tree
=
GenerateTree
()
self
.
change_org_if_need
()
self
.
change_org_if_need
()
self
.
nodes
=
None
self
.
nodes
=
None
self
.
_nodes
=
None
@staticmethod
@staticmethod
def
change_org_if_need
():
def
change_org_if_need
():
...
@@ -380,29 +413,32 @@ class AssetPermissionUtil(AssetPermissionCacheMixin):
...
@@ -380,29 +413,32 @@ class AssetPermissionUtil(AssetPermissionCacheMixin):
返回用户/组授权规则直接关联的节点
返回用户/组授权规则直接关联的节点
:return: {node1: {system_user1: {'actions': set()},}}
:return: {node1: {system_user1: {'actions': set()},}}
"""
"""
queryset
=
FlatPermissionQueryset
(
)
nodes
=
defaultdict
(
lambda
:
defaultdict
(
int
)
)
for
perm
in
self
.
permissions
:
for
perm
in
self
.
permissions
:
actions
=
perm
.
action
actions
=
[
perm
.
actions
]
system_users
=
perm
.
system_users
.
all
()
system_users
=
perm
.
system_users
.
all
()
nodes
=
perm
.
nodes
.
all
()
_nodes
=
perm
.
nodes
.
all
()
queryset
.
add_many
(
nodes
,
system_users
,
actions
,
rtp
=
"nodes"
)
for
node
,
system_user
,
action
in
itertools
.
product
(
_nodes
,
system_users
,
actions
):
print
(
queryset
)
nodes
[
node
][
system_user
]
|=
action
return
queryset
.
group_by_resource
()
self
.
tree
.
add_nodes
(
nodes
)
return
nodes
@timeit
@timeit
def
get_assets_direct
(
self
):
def
get_assets_direct
(
self
):
"""
"""
返回用户授权规则直接关联的资产
返回用户授权规则直接关联的资产
:return: {asset1: {system_user1:
{'actions': set()}
,}}
:return: {asset1: {system_user1:
1
,}}
"""
"""
queryset
=
FlatPermissionQueryset
(
)
assets
=
defaultdict
(
lambda
:
defaultdict
(
int
)
)
for
perm
in
self
.
permissions
:
for
perm
in
self
.
permissions
:
action
=
perm
.
action
action
s
=
[
perm
.
actions
]
assets
=
perm
.
assets
.
all
(
)
_assets
=
perm
.
assets
.
all
()
.
prefetch_related
(
'nodes'
,
'protocols'
)
system_users
=
perm
.
system_users
.
all
()
system_users
=
perm
.
system_users
.
all
()
queryset
.
add_many
(
assets
,
system_users
,
action
,
rtp
=
"assets"
)
iterable
=
itertools
.
product
(
_assets
,
system_users
,
actions
)
print
(
queryset
)
for
asset
,
system_user
,
action
in
iterable
:
return
queryset
.
group_by_resource
()
assets
[
asset
][
system_user
]
|=
action
self
.
tree
.
add_assets
(
assets
)
return
assets
@timeit
@timeit
def
get_assets_without_cache
(
self
):
def
get_assets_without_cache
(
self
):
...
@@ -411,24 +447,34 @@ class AssetPermissionUtil(AssetPermissionCacheMixin):
...
@@ -411,24 +447,34 @@ class AssetPermissionUtil(AssetPermissionCacheMixin):
"""
"""
if
self
.
_assets
:
if
self
.
_assets
:
return
self
.
_assets
return
self
.
_assets
assets
=
self
.
get_assets_direct
()
nodes
=
self
.
get_nodes_direct
()
nodes
=
self
.
get_nodes_direct
()
print
(
"++++++++++++++++++++++"
)
pattern
=
set
()
print
(
assets
)
for
node
in
nodes
:
print
(
"---------------------"
)
pattern
.
add
(
r'^{0}$|^{0}:'
.
format
(
node
.
key
))
print
(
nodes
)
pattern
=
'|'
.
join
(
list
(
pattern
))
now
=
time
.
time
()
print
(
"Get node assets start"
)
if
pattern
:
assets
=
Asset
.
objects
.
filter
(
nodes__key__regex
=
pattern
)
\
.
prefetch_related
(
'nodes'
,
"protocols"
)
.
only
(
'id'
,
'hostname'
,
'ip'
)
.
distinct
()
else
:
assets
=
[]
assets
=
list
(
assets
)
print
(
"Get node assets end, using: {}"
.
format
(
time
.
time
()
-
now
))
self
.
tree
.
add_assets_without_system_users
(
assets
)
assets
=
self
.
tree
.
get_assets
()
self
.
_assets
=
assets
return
assets
@timeit
@timeit
def
get_nodes_with_assets_without_cache
(
self
):
def
get_nodes_with_assets_without_cache
(
self
):
"""
"""
返回节点并且包含资产
返回节点并且包含资产
{"node": {"asset
s": set("system_user"
)}}
{"node": {"asset
": {"system_user": 1}
)}}
:return:
:return:
"""
"""
assets
=
self
.
get_assets_without_cache
()
self
.
get_assets_without_cache
()
for
asset
,
system_users
in
assets
.
items
():
return
self
.
tree
.
get_nodes_with_assets
()
self
.
tree
.
add_asset
(
asset
,
system_users
)
return
self
.
tree
.
get_nodes
()
def
get_system_user_without_cache
(
self
):
def
get_system_user_without_cache
(
self
):
system_users
=
set
()
system_users
=
set
()
...
@@ -460,9 +506,7 @@ def sort_assets(assets, order_by='hostname', reverse=False):
...
@@ -460,9 +506,7 @@ def sort_assets(assets, order_by='hostname', reverse=False):
def
parse_node_to_tree_node
(
node
):
def
parse_node_to_tree_node
(
node
):
from
..
import
serializers
name
=
'{} ({})'
.
format
(
node
.
value
,
node
.
assets_amount
)
name
=
'{} ({})'
.
format
(
node
.
value
,
node
.
assets_amount
)
node_serializer
=
serializers
.
GrantedNodeSerializer
(
node
)
data
=
{
data
=
{
'id'
:
node
.
key
,
'id'
:
node
.
key
,
'name'
:
name
,
'name'
:
name
,
...
@@ -471,7 +515,11 @@ def parse_node_to_tree_node(node):
...
@@ -471,7 +515,11 @@ def parse_node_to_tree_node(node):
'isParent'
:
True
,
'isParent'
:
True
,
'open'
:
node
.
is_root
(),
'open'
:
node
.
is_root
(),
'meta'
:
{
'meta'
:
{
'node'
:
node_serializer
.
data
,
'node'
:
{
"id"
:
node
.
id
,
"key"
:
node
.
key
,
"value"
:
node
.
value
,
},
'type'
:
'node'
'type'
:
'node'
}
}
}
}
...
@@ -480,23 +528,21 @@ def parse_node_to_tree_node(node):
...
@@ -480,23 +528,21 @@ def parse_node_to_tree_node(node):
def
parse_asset_to_tree_node
(
node
,
asset
,
system_users
):
def
parse_asset_to_tree_node
(
node
,
asset
,
system_users
):
system_users_protocol_matched
=
[
s
for
s
in
system_users
if
asset
.
has_protocol
(
s
.
protocol
)]
icon_skin
=
'file'
icon_skin
=
'file'
if
asset
.
platform
.
lower
()
==
'windows'
:
if
asset
.
platform
.
lower
()
==
'windows'
:
icon_skin
=
'windows'
icon_skin
=
'windows'
elif
asset
.
platform
.
lower
()
==
'linux'
:
elif
asset
.
platform
.
lower
()
==
'linux'
:
icon_skin
=
'linux'
icon_skin
=
'linux'
system_users
=
[]
_
system_users
=
[]
for
system_user
in
system_users_protocol_matched
:
for
system_user
,
action
in
system_users
.
items
()
:
system_users
.
append
({
_
system_users
.
append
({
'id'
:
system_user
.
id
,
'id'
:
system_user
.
id
,
'name'
:
system_user
.
name
,
'name'
:
system_user
.
name
,
'username'
:
system_user
.
username
,
'username'
:
system_user
.
username
,
'protocol'
:
system_user
.
protocol
,
'protocol'
:
system_user
.
protocol
,
'priority'
:
system_user
.
priority
,
'priority'
:
system_user
.
priority
,
'login_mode'
:
system_user
.
login_mode
,
'login_mode'
:
system_user
.
login_mode
,
'actions'
:
[
action
.
name
for
action
in
system_user
.
actions
],
'actions'
:
[
ActionFlag
.
value_to_choices
(
action
)],
'comment'
:
system_user
.
comment
,
})
})
data
=
{
data
=
{
'id'
:
str
(
asset
.
id
),
'id'
:
str
(
asset
.
id
),
...
@@ -507,7 +553,7 @@ def parse_asset_to_tree_node(node, asset, system_users):
...
@@ -507,7 +553,7 @@ def parse_asset_to_tree_node(node, asset, system_users):
'open'
:
False
,
'open'
:
False
,
'iconSkin'
:
icon_skin
,
'iconSkin'
:
icon_skin
,
'meta'
:
{
'meta'
:
{
'system_users'
:
system_users
,
'system_users'
:
_
system_users
,
'type'
:
'asset'
,
'type'
:
'asset'
,
'asset'
:
{
'asset'
:
{
'id'
:
asset
.
id
,
'id'
:
asset
.
id
,
...
...
This diff is collapsed.
Click to expand it.
apps/perms/utils/test_asset_permission.py
deleted
100644 → 0
View file @
8f699fa3
# -*- coding: utf-8 -*-
#
from
django.test
import
TestCase
from
assets.models
import
Node
,
SystemUser
from
.asset_permission
import
FlatPermission
from
..models
import
ActionFlag
class
TestFlatPermissionEqual
(
TestCase
):
def
setUp
(
self
):
node1
=
Node
(
value
=
"parent"
,
key
=
"1:1"
)
node2
=
Node
(
value
=
"child"
,
key
=
"1:1:1"
)
system_user1
=
SystemUser
(
username
=
"name1"
,
name
=
"name1"
,
priority
=
20
)
system_user2
=
SystemUser
(
username
=
"name2"
,
name
=
"name2"
,
priority
=
10
)
action1
=
ActionFlag
.
ALL
action2
=
ActionFlag
.
CONNECT
action3
=
ActionFlag
.
UPDOWNLOAD
perm1
=
FlatPermission
(
node1
,
system_user1
,
action1
)
perm2
=
FlatPermission
(
node2
,
system_user1
,
action1
)
perm3
=
FlatPermission
(
node2
,
system_user2
,
action1
)
self
.
groups
=
(
(
perm1
,
perm2
,
True
),
(
perm1
,
perm3
,
True
),
)
def
test_equal
(
self
):
for
k
,
k2
,
wanted
in
self
.
groups
:
if
(
k
==
k2
)
!=
wanted
:
print
(
"Not equal {} {}"
,
k
,
k2
)
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment