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
8f699fa3
Commit
8f699fa3
authored
Jun 30, 2019
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Update] 修改Permission
parent
8e9b3f13
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
183 additions
and
103 deletions
+183
-103
asset_permission.py
apps/perms/forms/asset_permission.py
+22
-5
0006_auto_20190628_1921.py
apps/perms/migrations/0006_auto_20190628_1921.py
+1
-4
asset_permission.py
apps/perms/models/asset_permission.py
+30
-9
asset_permission.py
apps/perms/serializers/asset_permission.py
+24
-2
asset_permission_create_update.html
...perms/templates/perms/asset_permission_create_update.html
+8
-11
asset_permission_list.html
apps/perms/templates/perms/asset_permission_list.html
+2
-2
asset_permission.py
apps/perms/utils/asset_permission.py
+57
-69
test_asset_permission.py
apps/perms/utils/test_asset_permission.py
+36
-0
asset_permission.py
apps/perms/views/asset_permission.py
+3
-1
No files found.
apps/perms/forms/asset_permission.py
View file @
8f699fa3
...
...
@@ -7,15 +7,36 @@ from django.utils.translation import ugettext_lazy as _
from
orgs.mixins
import
OrgModelForm
from
orgs.utils
import
current_org
from
perms.models
import
AssetPermission
from
assets.models
import
Asset
,
Node
from
..models
import
AssetPermission
,
ActionFlag
__all__
=
[
'AssetPermissionForm'
,
]
class
ActionField
(
forms
.
MultipleChoiceField
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
kwargs
[
'choices'
]
=
ActionFlag
.
CHOICES
kwargs
[
'initial'
]
=
ActionFlag
.
ALL
kwargs
[
'label'
]
=
_
(
"Action"
)
kwargs
[
'widget'
]
=
forms
.
CheckboxSelectMultiple
()
super
()
.
__init__
(
*
args
,
**
kwargs
)
def
to_python
(
self
,
value
):
value
=
super
()
.
to_python
(
value
)
return
ActionFlag
.
choices_to_value
(
value
)
def
prepare_value
(
self
,
value
):
if
value
is
None
:
return
value
value
=
ActionFlag
.
value_to_choices
(
value
)
return
value
class
AssetPermissionForm
(
OrgModelForm
):
action
=
ActionField
()
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
()
.
__init__
(
*
args
,
**
kwargs
)
users_field
=
self
.
fields
.
get
(
'users'
)
...
...
@@ -32,10 +53,6 @@ class AssetPermissionForm(OrgModelForm):
nodes_field
=
self
.
fields
[
'nodes'
]
nodes_field
.
_queryset
=
Node
.
get_queryset
()
def
clean_action
(
self
):
actions
=
self
.
cleaned_data
.
get
(
"action"
)
return
reduce
(
lambda
x
,
y
:
x
|
y
,
actions
)
class
Meta
:
model
=
AssetPermission
exclude
=
(
...
...
apps/perms/migrations/0006_auto_20190628_1921.py
View file @
8f699fa3
...
...
@@ -36,10 +36,7 @@ class Migration(migrations.Migration):
migrations
.
AddField
(
model_name
=
'assetpermission'
,
name
=
'action'
,
field
=
models
.
IntegerField
(
choices
=
[(
255
,
'All'
),
(
1
,
'Connect'
),
(
2
,
'Upload file'
),
(
6
,
'Upload download'
),
(
4
,
'Download file'
)],
default
=
255
,
verbose_name
=
'Action'
),
field
=
models
.
IntegerField
(
choices
=
[(
255
,
'All'
),
(
1
,
'Connect'
),
(
2
,
'Upload file'
),
(
5
,
'Upload download'
),
(
4
,
'Download file'
)],
default
=
255
,
verbose_name
=
'Action'
),
),
migrations
.
RunPython
(
migrate_old_actions
),
]
apps/perms/models/asset_permission.py
View file @
8f699fa3
import
uuid
from
functools
import
reduce
from
django.db
import
models
from
django.utils.translation
import
ugettext_lazy
as
_
...
...
@@ -37,17 +38,41 @@ class ActionFlag:
CONNECT
=
0
b00000001
UPLOAD
=
0
b00000010
DOWNLOAD
=
0
b00000100
UPDOWNLOAD
=
CONNECT
|
DOWNLOAD
UPDOWNLOAD
=
UPLOAD
|
DOWNLOAD
CONNECT_UPLOADOWN
=
CONNECT
|
UPDOWNLOAD
ALL
=
0
b11111111
NAME_MAP
=
{
"connect"
:
CONNECT
,
"upload"
:
UPLOAD
,
"download"
:
DOWNLOAD
,
"updownload"
:
UPDOWNLOAD
,
"all"
:
ALL
,
}
CHOICES
=
(
(
ALL
,
_
(
'All'
)),
(
CONNECT
,
_
(
'Connect'
)),
(
UPLOAD
,
_
(
'Upload file'
)),
(
UPDOWNLOAD
,
_
(
"Upload download"
)),
(
UPLOAD
,
_
(
'Upload file'
)),
(
DOWNLOAD
,
_
(
'Download file'
)),
)
@classmethod
def
value_to_choices
(
cls
,
value
):
value
=
int
(
value
)
if
value
==
cls
.
ALL
:
return
[
cls
.
ALL
]
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
def
choices_to_value
(
cls
,
value
):
return
reduce
(
lambda
x
,
y
:
int
(
x
)
|
int
(
y
),
value
)
class
AssetPermission
(
BasePermission
):
assets
=
models
.
ManyToManyField
(
'assets.Asset'
,
related_name
=
'granted_by_permissions'
,
blank
=
True
,
verbose_name
=
_
(
"Asset"
))
...
...
@@ -60,13 +85,9 @@ class AssetPermission(BasePermission):
unique_together
=
[(
'org_id'
,
'name'
)]
verbose_name
=
_
(
"Asset permission"
)
def
get_all_assets
(
self
):
assets
=
set
(
self
.
assets
.
all
())
for
node
in
self
.
nodes
.
all
():
_assets
=
node
.
get_all_assets
()
set_or_append_attr_bulk
(
_assets
,
'inherit'
,
node
.
value
)
assets
.
update
(
set
(
_assets
))
return
assets
@classmethod
def
get_queryset_with_prefetch
(
cls
):
return
cls
.
objects
.
all
()
.
valid
()
.
prefetch_related
(
'nodes'
,
'assets'
,
'system_users'
)
class
NodePermission
(
OrgModelMixin
):
...
...
apps/perms/serializers/asset_permission.py
View file @
8f699fa3
# -*- coding: utf-8 -*-
#
from
functools
import
reduce
from
rest_framework
import
serializers
from
common.fields
import
StringManyToManyField
from
orgs.mixins
import
BulkOrgResourceModelSerializer
from
perms.models
import
AssetPermission
,
Action
from
perms.models
import
AssetPermission
,
Action
,
ActionFlag
from
assets.models
import
Node
from
assets.serializers
import
AssetGrantedSerializer
...
...
@@ -17,7 +18,28 @@ __all__ = [
]
class
ActionField
(
serializers
.
MultipleChoiceField
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
kwargs
[
'choices'
]
=
ActionFlag
.
CHOICES
super
()
.
__init__
(
*
args
,
**
kwargs
)
def
to_representation
(
self
,
value
):
return
ActionFlag
.
value_to_choices
(
value
)
def
to_internal_value
(
self
,
data
):
return
ActionFlag
.
choices_to_value
(
data
)
class
ActionDisplayField
(
ActionField
):
def
to_representation
(
self
,
value
):
values
=
super
()
.
to_representation
(
value
)
choices
=
dict
(
ActionFlag
.
CHOICES
)
return
[
choices
.
get
(
i
)
for
i
in
values
]
class
AssetPermissionCreateUpdateSerializer
(
BulkOrgResourceModelSerializer
):
action
=
ActionField
()
class
Meta
:
model
=
AssetPermission
exclude
=
(
'created_by'
,
'date_created'
)
...
...
@@ -29,7 +51,7 @@ class AssetPermissionListSerializer(BulkOrgResourceModelSerializer):
assets
=
StringManyToManyField
(
many
=
True
,
read_only
=
True
)
nodes
=
StringManyToManyField
(
many
=
True
,
read_only
=
True
)
system_users
=
StringManyToManyField
(
many
=
True
,
read_only
=
True
)
action
=
serializers
.
IntegerField
(
read_only
=
True
)
action
=
ActionDisplayField
(
)
is_valid
=
serializers
.
BooleanField
()
is_expired
=
serializers
.
BooleanField
()
...
...
apps/perms/templates/perms/asset_permission_create_update.html
View file @
8f699fa3
...
...
@@ -110,6 +110,7 @@ var dateOptions = {
format
:
'YYYY-MM-DD HH:mm'
}
};
var
api_action
=
"{{ api_action }}"
;
$
(
document
).
ready
(
function
()
{
$
(
'.select2'
).
select2
({
closeOnSelect
:
false
...
...
@@ -147,21 +148,17 @@ $(document).ready(function () {
.
on
(
"submit"
,
"form"
,
function
(
evt
)
{
evt
.
preventDefault
();
var
the_url
=
'{% url '
api
-
perms
:
asset
-
permission
-
list
' %}'
;
var
redirect_to
=
'{% url "perms:asset-permission-list" %}'
;
var
method
=
"POST"
;
{
%
if
api_action
==
"update"
%
}
the_url
=
'{% url '
api
-
perms
:
asset
-
permission
-
detail
' pk=object.id %}'
;
method
=
"PUT"
;
{
%
endif
%
}
var
redirect_to
=
'{% url "perms:asset-permission-list" %}'
;
var
form
=
$
(
"form"
);
var
data
=
form
.
serializeObject
();
console
.
log
(
data
)
var
actions
=
data
.
action
;
var
action
=
0
;
for
(
i
=
0
;
i
<
actions
.
length
;
i
++
)
{
console
.
log
(
actions
[
i
])
action
|=
actions
[
i
];
}
data
.
action
=
action
;
objectAttrsIsList
(
data
,
[
'users'
,
'user_groups'
,
'system_users'
,
'nodes'
,
'assets'
]);
objectAttrsIsList
(
data
,
[
'users'
,
'user_groups'
,
'system_users'
,
'nodes'
,
'assets'
,
'actions'
]);
objectAttrsIsDatetime
(
data
,
[
'date_start'
,
'date_expired'
]);
objectAttrsIsBool
(
data
,
[
'is_active'
])
objectAttrsIsBool
(
data
,
[
'is_active'
])
;
console
.
log
(
data
)
var
props
=
{
url
:
the_url
,
...
...
apps/perms/templates/perms/asset_permission_list.html
View file @
8f699fa3
...
...
@@ -122,8 +122,8 @@ function format(d) {
if
(
d
.
system_users
.
length
>
0
)
{
data
+=
makeLabel
([
"{% trans 'System user' %}"
,
d
.
system_users
.
join
(
", "
)])
}
if
(
d
.
action
s
.
length
>
0
)
{
data
+=
makeLabel
([
"{% trans 'Action' %}"
,
d
.
action
s
.
join
(
", "
)])
if
(
d
.
action
.
length
>
0
)
{
data
+=
makeLabel
([
"{% trans 'Action' %}"
,
d
.
action
.
join
(
", "
)])
}
return
data
}
...
...
apps/perms/utils/asset_permission.py
View file @
8f699fa3
...
...
@@ -103,11 +103,11 @@ def get_user_permissions(user, include_group=True):
arg
=
Q
(
users
=
user
)
|
Q
(
user_groups__in
=
groups
)
else
:
arg
=
Q
(
users
=
user
)
return
AssetPermission
.
objects
.
valid
()
.
filter
(
arg
)
return
AssetPermission
.
get_queryset_with_prefetch
()
.
filter
(
arg
)
def
get_user_group_permissions
(
user_group
):
return
AssetPermission
.
objects
.
valid
()
.
filter
(
return
AssetPermission
.
get_queryset_with_prefetch
()
.
filter
(
user_groups
=
user_group
)
...
...
@@ -282,36 +282,55 @@ class AssetPermissionCacheMixin:
cache
.
delete_pattern
(
key
)
class
FlatPermissionQueryset
:
def
__init__
(
self
):
self
.
queryset
=
defaultdict
(
list
)
def
add
(
self
,
permission
):
self
.
queryset
[
permission
.
id
]
.
append
(
permission
)
def
add_many
(
self
,
assets_or_nodes
,
system_users
,
actions
):
if
any
([
assets_or_nodes
,
system_users
,
actions
]):
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
,
actions
)
iterable
=
itertools
.
product
(
assets_or_nodes
,
system_users
,
[
action
]
)
for
source
,
sysuser
,
action
in
iterable
:
permission
=
FlatPermission
(
source
,
sysuser
,
action
)
permission
=
FlatPermission
(
source
,
sysuser
,
action
,
rtp
=
rtp
)
print
(
"ADDDDDDDDDDDDDDDd"
)
self
.
add
(
permission
)
def
clean
(
self
):
pass
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
,
asset_or_node
,
system_user
,
action
):
self
.
id
=
asset_or_node
.
id
self
.
source
=
asset_or_node
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
):
pass
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
):
...
...
@@ -355,33 +374,20 @@ class AssetPermissionUtil(AssetPermissionCacheMixin):
self
.
_permissions
=
self
.
permissions
.
filter
(
**
filters
)
self
.
_filter_id
=
md5
(
filters_json
.
encode
())
.
hexdigest
()
@staticmethod
@timeit
def
_structured_system_user
(
system_users
,
actions
):
"""
结构化系统用户
:param system_users:
:param actions:
:return: {system_user1: {'actions': set(), }, }
"""
_attr
=
{
'actions'
:
set
(
actions
)}
_system_users
=
{
system_user
:
_attr
for
system_user
in
system_users
}
return
_system_users
@timeit
def
get_nodes_direct
(
self
):
"""
返回用户/组授权规则直接关联的节点
:return: {node1: {system_user1: {'actions': set()},}}
"""
nodes
=
FlatPermissionQueryset
()
permissions
=
self
.
permissions
for
perm
in
permissions
:
actions
=
perm
.
actions
.
all
()
queryset
=
FlatPermissionQueryset
()
for
perm
in
self
.
permissions
:
actions
=
perm
.
action
system_users
=
perm
.
system_users
.
all
()
_nodes
=
perm
.
nodes
.
all
()
nodes
.
add_many
(
_nodes
,
system_users
,
actions
)
return
nodes
nodes
=
perm
.
nodes
.
all
()
queryset
.
add_many
(
nodes
,
system_users
,
actions
,
rtp
=
"nodes"
)
print
(
queryset
)
return
queryset
.
group_by_resource
()
@timeit
def
get_assets_direct
(
self
):
...
...
@@ -389,15 +395,14 @@ class AssetPermissionUtil(AssetPermissionCacheMixin):
返回用户授权规则直接关联的资产
:return: {asset1: {system_user1: {'actions': set()},}}
"""
assets
=
defaultdict
(
dict
)
permissions
=
self
.
permissions
.
prefetch_related
(
'assets'
,
'system_users'
)
for
perm
in
permissions
:
actions
=
perm
.
actions
.
all
()
for
asset
in
perm
.
assets
.
all
()
.
valid
()
.
prefetch_related
(
'nodes'
):
system_users
=
perm
.
system_users
.
filter
(
protocol__in
=
asset
.
protocols_name
)
system_users
=
self
.
_structured_system_user
(
system_users
,
actions
)
assets
[
asset
]
.
update
(
system_users
)
return
assets
queryset
=
FlatPermissionQueryset
()
for
perm
in
self
.
permissions
:
action
=
perm
.
action
assets
=
perm
.
assets
.
all
()
system_users
=
perm
.
system_users
.
all
()
queryset
.
add_many
(
assets
,
system_users
,
action
,
rtp
=
"assets"
)
print
(
queryset
)
return
queryset
.
group_by_resource
()
@timeit
def
get_assets_without_cache
(
self
):
...
...
@@ -408,27 +413,10 @@ class AssetPermissionUtil(AssetPermissionCacheMixin):
return
self
.
_assets
assets
=
self
.
get_assets_direct
()
nodes
=
self
.
get_nodes_direct
()
# for node, system_users in nodes.items():
# print(">>>>> Node<<<<<<<<<<<<: ", node.value)
# _assets = list(node.get_all_valid_assets())
# for asset in _assets:
# for system_user, attr_dict in system_users.items():
# if not asset.has_protocol(system_user.protocol):
# continue
# if system_user in assets[asset]:
# actions = assets[asset][system_user]['actions']
# attr_dict['actions'].update(actions)
# system_users.update({system_user: attr_dict})
# assets[asset].update(system_users)
__assets
=
defaultdict
(
set
)
for
asset
,
system_users
in
assets
.
items
():
for
system_user
,
attr_dict
in
system_users
.
items
():
setattr
(
system_user
,
'actions'
,
attr_dict
[
'actions'
])
__assets
[
asset
]
=
set
(
system_users
.
keys
())
self
.
_assets
=
__assets
return
self
.
_assets
print
(
"++++++++++++++++++++++"
)
print
(
assets
)
print
(
"---------------------"
)
print
(
nodes
)
@timeit
def
get_nodes_with_assets_without_cache
(
self
):
...
...
apps/perms/utils/test_asset_permission.py
0 → 100644
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
)
apps/perms/views/asset_permission.py
View file @
8f699fa3
...
...
@@ -64,6 +64,7 @@ class AssetPermissionCreateView(PermissionsMixin, CreateView):
context
=
{
'app'
:
_
(
'Perms'
),
'action'
:
_
(
'Create asset permission'
),
'api_action'
:
"create"
,
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
...
...
@@ -79,7 +80,8 @@ class AssetPermissionUpdateView(PermissionsMixin, UpdateView):
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
_
(
'Perms'
),
'action'
:
_
(
'Update asset permission'
)
'action'
:
_
(
'Update asset permission'
),
'api_action'
:
"update"
,
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
...
...
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