Skip to content

Commit

Permalink
Merge f44aaf5 into 0f61bee
Browse files Browse the repository at this point in the history
  • Loading branch information
iambibhas committed Jul 23, 2020
2 parents 0f61bee + f44aaf5 commit e02138d
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 28 deletions.
57 changes: 29 additions & 28 deletions coaster/sqlalchemy/roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,34 +305,35 @@ def _role_is_present(self, role):
offer_map = self.obj.__relationship_role_offer_map__.get(relattr)
if (relattr, actor_attr) not in self._scanned_granted_via:
relationship = self._get_relationship(relattr)
# Optimization: does the same relationship grant other roles
# via the same actor_attr? Gather those roles and check all of
# them together. However, we will use a single role offer map
# and not consult the one specified on the other roles. They are
# expected to be identical. This is guaranteed if the offer map
# was specified using `with_roles(grants_via=)` but not if
# specified directly in `__roles__[role]['granted_via']`.
possible_roles = {role}
for arole, actions in self.obj.__roles__.items():
if (
arole != role
and 'granted_via' in actions
and relattr in actions['granted_via']
and actions['granted_via'][relattr] == actor_attr
):
possible_roles.add(arole)

granted_roles = _roles_via_relationship(
self.actor,
relationship,
actor_attr,
possible_roles,
offer_map,
)
self._present.update(granted_roles)
self._scanned_granted_via.add((relattr, actor_attr))
if role in granted_roles:
return True
if relationship is not None:
# Optimization: does the same relationship grant other roles
# via the same actor_attr? Gather those roles and check all of
# them together. However, we will use a single role offer map
# and not consult the one specified on the other roles. They are
# expected to be identical. This is guaranteed if the offer map
# was specified using `with_roles(grants_via=)` but not if
# specified directly in `__roles__[role]['granted_via']`.
possible_roles = {role}
for arole, actions in self.obj.__roles__.items():
if (
arole != role
and 'granted_via' in actions
and relattr in actions['granted_via']
and actions['granted_via'][relattr] == actor_attr
):
possible_roles.add(arole)

granted_roles = _roles_via_relationship(
self.actor,
relationship,
actor_attr,
possible_roles,
offer_map,
)
self._present.update(granted_roles)
self._scanned_granted_via.add((relattr, actor_attr))
if role in granted_roles:
return True
# granted_by says a role is granted by the actor being present in a
# relationship
if 'granted_by' in self.obj.__roles__[role]:
Expand Down
3 changes: 3 additions & 0 deletions tests/test_sqlalchemy_roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,7 @@ def test_granted_via(self):
u4 = RoleUser()
parent = MultiroleParent(user=u1)
document = MultiroleDocument(parent=parent)
document_no_parent = MultiroleDocument(parent=None)
child = MultiroleChild(parent=document)
m1 = RoleMembership(doc=document, user=u1, role1=True, role2=False, role3=False)
m2 = RoleMembership(doc=document, user=u2, role1=True, role2=True, role3=False)
Expand All @@ -889,6 +890,8 @@ def test_granted_via(self):
assert 'parent_role' not in document.roles_for(u2)
assert 'parent_role' not in document.roles_for(u3)

assert 'parent_role' not in document_no_parent.roles_for(u1)

# parent grants prole1 and prole2. Testing for one auto-loads the other
proles = parent.roles_for(u1)
assert 'prole1' not in proles._present
Expand Down

0 comments on commit e02138d

Please sign in to comment.