Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
U
uffd
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Operate
Terraform modules
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Luca (strifel)
uffd
Commits
32442257
Commit
32442257
authored
3 years ago
by
Julian
Committed by
Julian
3 years ago
Browse files
Options
Downloads
Patches
Plain Diff
Replaced in-python recursion flattening with in-db recursive cte
parent
d482047a
No related branches found
No related tags found
No related merge requests found
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
tests/test_role.py
+9
-21
9 additions, 21 deletions
tests/test_role.py
uffd/role/models.py
+25
-17
25 additions, 17 deletions
uffd/role/models.py
with
34 additions
and
38 deletions
tests/test_role.py
+
9
−
21
View file @
32442257
...
...
@@ -9,32 +9,12 @@ from uffd.ldap import ldap
from
uffd
import
user
from
uffd.user.models
import
User
,
Group
from
uffd.role.models
import
flatten_recursive
,
Role
,
RoleGroup
from
uffd.role.models
import
Role
,
RoleGroup
from
uffd.mfa.models
import
TOTPMethod
from
uffd
import
create_app
,
db
from
utils
import
dump
,
UffdTestCase
class
TestPrimitives
(
unittest
.
TestCase
):
def
test_flatten_recursive
(
self
):
class
Node
:
def
__init__
(
self
,
*
neighbors
):
self
.
neighbors
=
set
(
neighbors
or
set
())
cycle
=
Node
()
cycle
.
neighbors
.
add
(
cycle
)
common
=
Node
(
cycle
)
intermediate1
=
Node
(
common
)
intermediate2
=
Node
(
common
,
intermediate1
)
stub
=
Node
()
backref
=
Node
()
start1
=
Node
(
intermediate1
,
intermediate2
,
stub
,
backref
)
backref
.
neighbors
.
add
(
start1
)
start2
=
Node
()
self
.
assertSetEqual
(
flatten_recursive
({
start1
,
start2
},
'
neighbors
'
),
{
start1
,
start2
,
backref
,
stub
,
intermediate1
,
intermediate2
,
common
,
cycle
})
self
.
assertSetEqual
(
flatten_recursive
(
set
(),
'
neighbors
'
),
set
())
class
TestUserRoleAttributes
(
UffdTestCase
):
def
test_roles_effective
(
self
):
for
user
in
User
.
query
.
filter_by
(
loginname
=
'
service
'
).
all
():
...
...
@@ -103,6 +83,8 @@ class TestRoleModel(UffdTestCase):
included_role
=
Role
(
name
=
'
included
'
)
direct_role
=
Role
(
name
=
'
direct
'
,
members
=
[
user1
,
user2
,
service
],
included_roles
=
[
included_role
])
empty_role
=
Role
(
name
=
'
empty
'
,
included_roles
=
[
included_role
])
db
.
session
.
add_all
([
included_by_default_role
,
default_role
,
included_role
,
direct_role
,
empty_role
])
db
.
session
.
commit
()
self
.
assertSetEqual
(
included_by_default_role
.
members_effective
,
{
user1
,
user2
})
self
.
assertSetEqual
(
default_role
.
members_effective
,
{
user1
,
user2
})
self
.
assertSetEqual
(
included_role
.
members_effective
,
{
user1
,
user2
,
service
})
...
...
@@ -116,10 +98,13 @@ class TestRoleModel(UffdTestCase):
role1
=
Role
(
name
=
'
role1
'
,
included_roles
=
[
baserole
])
role2
=
Role
(
name
=
'
role2
'
,
included_roles
=
[
baserole
])
role3
=
Role
(
name
=
'
role3
'
,
included_roles
=
[
role1
,
role2
])
db
.
session
.
add_all
([
baserole
,
role1
,
role2
,
role3
])
db
.
session
.
commit
()
self
.
assertSetEqual
(
role1
.
included_roles_recursive
,
{
baserole
})
self
.
assertSetEqual
(
role2
.
included_roles_recursive
,
{
baserole
})
self
.
assertSetEqual
(
role3
.
included_roles_recursive
,
{
baserole
,
role1
,
role2
})
baserole
.
included_roles
.
append
(
role1
)
db
.
session
.
commit
()
self
.
assertSetEqual
(
role3
.
included_roles_recursive
,
{
baserole
,
role1
,
role2
})
def
test_groups_effective
(
self
):
...
...
@@ -127,6 +112,8 @@ class TestRoleModel(UffdTestCase):
group2
=
self
.
get_access_group
()
baserole
=
Role
(
name
=
'
base
'
,
groups
=
{
group1
:
RoleGroup
(
group
=
group1
)})
role1
=
Role
(
name
=
'
role1
'
,
groups
=
{
group2
:
RoleGroup
(
group
=
group2
)},
included_roles
=
[
baserole
])
db
.
session
.
add_all
([
baserole
,
role1
])
db
.
session
.
commit
()
self
.
assertSetEqual
(
baserole
.
groups_effective
,
{
group1
})
self
.
assertSetEqual
(
role1
.
groups_effective
,
{
group1
,
group2
})
...
...
@@ -141,6 +128,7 @@ class TestRoleModel(UffdTestCase):
baserole
=
Role
(
name
=
'
base
'
,
members
=
[
user1
],
groups
=
{
group1
:
RoleGroup
(
group
=
group1
)})
role1
=
Role
(
name
=
'
role1
'
,
members
=
[
user2
],
groups
=
{
group2
:
RoleGroup
(
group
=
group2
)},
included_roles
=
[
baserole
])
db
.
session
.
add_all
([
baserole
,
role1
])
db
.
session
.
commit
()
baserole
.
update_member_groups
()
role1
.
update_member_groups
()
self
.
assertSetEqual
(
set
(
user1
.
groups
),
{
group1
})
...
...
This diff is collapsed.
Click to expand it.
uffd/role/models.py
+
25
−
17
View file @
32442257
...
...
@@ -35,22 +35,17 @@ role_inclusion = db.Table('role-inclusion',
Column
(
'
included_role_id
'
,
Integer
,
ForeignKey
(
'
role.id
'
),
primary_key
=
True
)
)
def
flatten_recursive
(
objs
,
attr
):
'''
Returns a set of objects and all objects included in object.`attr` recursivly while avoiding loops
'''
objs
=
set
(
objs
)
new_objs
=
set
(
objs
)
while
new_objs
:
for
obj
in
getattr
(
new_objs
.
pop
(),
attr
):
if
obj
not
in
objs
:
objs
.
add
(
obj
)
new_objs
.
add
(
obj
)
return
objs
def
get_user_roles_effective
(
user
):
base
=
set
(
user
.
roles
)
if
not
user
.
is_service_user
:
base
.
update
(
Role
.
query
.
filter_by
(
is_default
=
True
))
return
flatten_recursive
(
base
,
'
included_roles
'
)
direct_roles
=
db
.
session
.
query
(
Role
).
join
(
RoleUser
)
\
.
filter
(
RoleUser
.
dn
==
user
.
dn
)
# pylint: disable=singleton-comparison
base_roles
=
db
.
session
.
query
(
Role
).
filter
(
db
.
and_
(
Role
.
is_default
==
True
,
user
.
is_service_user
is
False
))
cte
=
direct_roles
.
union
(
base_roles
).
cte
(
'
cte
'
,
recursive
=
True
)
rquery
=
cte
.
union
(
db
.
session
.
query
(
Role
)
\
.
join
(
role_inclusion
,
Role
.
id
==
role_inclusion
.
c
.
included_role_id
)
\
.
join
(
cte
,
role_inclusion
.
c
.
role_id
==
cte
.
c
.
role_id
))
return
set
(
Role
.
query
.
join
(
rquery
,
rquery
.
c
.
role_id
==
Role
.
id
).
all
())
User
.
roles_effective
=
property
(
get_user_roles_effective
)
...
...
@@ -115,8 +110,14 @@ class Role(db.Model):
@property
def
members_effective
(
self
):
cte
=
db
.
session
.
query
(
Role
).
filter
(
Role
.
id
==
self
.
id
)
\
.
cte
(
'
cte
'
,
recursive
=
True
)
rquery
=
cte
.
union
(
db
.
session
.
query
(
Role
)
\
.
join
(
role_inclusion
,
Role
.
id
==
role_inclusion
.
c
.
role_id
)
\
.
join
(
cte
,
role_inclusion
.
c
.
included_role_id
==
cte
.
c
.
id
))
including_roles_recursive
=
Role
.
query
.
join
(
rquery
,
rquery
.
c
.
id
==
Role
.
id
).
all
()
members
=
set
()
for
role
in
flatten_recursive
([
self
],
'
including_roles
'
)
:
for
role
in
including_roles
_recursive
:
members
.
update
(
role
.
members
)
if
role
.
is_default
:
members
.
update
([
user
for
user
in
User
.
query
.
all
()
if
not
user
.
is_service_user
])
...
...
@@ -124,7 +125,14 @@ class Role(db.Model):
@property
def
included_roles_recursive
(
self
):
return
flatten_recursive
(
self
.
included_roles
,
'
included_roles
'
)
cte
=
db
.
session
.
query
(
Role
)
\
.
join
(
role_inclusion
,
Role
.
id
==
role_inclusion
.
c
.
included_role_id
)
\
.
filter
(
role_inclusion
.
c
.
role_id
==
self
.
id
)
\
.
cte
(
'
cte
'
,
recursive
=
True
)
rquery
=
cte
.
union
(
db
.
session
.
query
(
Role
)
\
.
join
(
role_inclusion
,
Role
.
id
==
role_inclusion
.
c
.
included_role_id
)
\
.
join
(
cte
,
role_inclusion
.
c
.
role_id
==
cte
.
c
.
id
))
return
set
(
Role
.
query
.
join
(
rquery
,
rquery
.
c
.
id
==
Role
.
id
).
all
())
@property
def
groups_effective
(
self
):
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment