mirror of
https://github.com/ansible/awx.git
synced 2026-06-24 16:17:51 -02:30
move code linting to a stricter pep8-esque auto-formatting tool, black
This commit is contained in:
@@ -15,7 +15,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
# AWX
|
||||
from awx.api.versioning import reverse
|
||||
from django.contrib.auth.models import User # noqa
|
||||
from django.contrib.auth.models import User # noqa
|
||||
|
||||
__all__ = [
|
||||
'Role',
|
||||
@@ -23,13 +23,13 @@ __all__ = [
|
||||
'get_roles_on_resource',
|
||||
'ROLE_SINGLETON_SYSTEM_ADMINISTRATOR',
|
||||
'ROLE_SINGLETON_SYSTEM_AUDITOR',
|
||||
'role_summary_fields_generator'
|
||||
'role_summary_fields_generator',
|
||||
]
|
||||
|
||||
logger = logging.getLogger('awx.main.models.rbac')
|
||||
|
||||
ROLE_SINGLETON_SYSTEM_ADMINISTRATOR='system_administrator'
|
||||
ROLE_SINGLETON_SYSTEM_AUDITOR='system_auditor'
|
||||
ROLE_SINGLETON_SYSTEM_ADMINISTRATOR = 'system_administrator'
|
||||
ROLE_SINGLETON_SYSTEM_AUDITOR = 'system_auditor'
|
||||
|
||||
role_names = {
|
||||
'system_administrator': _('System Administrator'),
|
||||
@@ -77,15 +77,16 @@ role_descriptions = {
|
||||
}
|
||||
|
||||
|
||||
tls = threading.local() # thread local storage
|
||||
tls = threading.local() # thread local storage
|
||||
|
||||
|
||||
def check_singleton(func):
|
||||
'''
|
||||
"""
|
||||
check_singleton is a decorator that checks if a user given
|
||||
to a `visible_roles` method is in either of our singleton roles (Admin, Auditor)
|
||||
and if so, returns their full list of roles without filtering.
|
||||
'''
|
||||
"""
|
||||
|
||||
def wrapper(*args, **kwargs):
|
||||
sys_admin = Role.singleton(ROLE_SINGLETON_SYSTEM_ADMINISTRATOR)
|
||||
sys_audit = Role.singleton(ROLE_SINGLETON_SYSTEM_AUDITOR)
|
||||
@@ -95,12 +96,13 @@ def check_singleton(func):
|
||||
return args[1]
|
||||
return Role.objects.all()
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def batch_role_ancestor_rebuilding(allow_nesting=False):
|
||||
'''
|
||||
"""
|
||||
Batches the role ancestor rebuild work necessary whenever role-role
|
||||
relations change. This can result in a big speedup when performing
|
||||
any bulk manipulation.
|
||||
@@ -108,7 +110,7 @@ def batch_role_ancestor_rebuilding(allow_nesting=False):
|
||||
WARNING: Calls to anything related to checking access/permissions
|
||||
while within the context of the batch_role_ancestor_rebuilding will
|
||||
likely not work.
|
||||
'''
|
||||
"""
|
||||
|
||||
batch_role_rebuilding = getattr(tls, 'batch_role_rebuilding', False)
|
||||
|
||||
@@ -131,17 +133,15 @@ def batch_role_ancestor_rebuilding(allow_nesting=False):
|
||||
|
||||
|
||||
class Role(models.Model):
|
||||
'''
|
||||
"""
|
||||
Role model
|
||||
'''
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
app_label = 'main'
|
||||
verbose_name_plural = _('roles')
|
||||
db_table = 'main_rbac_roles'
|
||||
index_together = [
|
||||
("content_type", "object_id")
|
||||
]
|
||||
index_together = [("content_type", "object_id")]
|
||||
ordering = ("content_type", "object_id")
|
||||
|
||||
role_field = models.TextField(null=False)
|
||||
@@ -149,11 +149,8 @@ class Role(models.Model):
|
||||
parents = models.ManyToManyField('Role', related_name='children')
|
||||
implicit_parents = models.TextField(null=False, default='[]')
|
||||
ancestors = models.ManyToManyField(
|
||||
'Role',
|
||||
through='RoleAncestorEntry',
|
||||
through_fields=('descendent', 'ancestor'),
|
||||
related_name='descendents'
|
||||
) # auto-generated by `rebuild_role_ancestor_list`
|
||||
'Role', through='RoleAncestorEntry', through_fields=('descendent', 'ancestor'), related_name='descendents'
|
||||
) # auto-generated by `rebuild_role_ancestor_list`
|
||||
members = models.ManyToManyField('auth.User', related_name='roles')
|
||||
content_type = models.ForeignKey(ContentType, null=True, default=None, on_delete=models.CASCADE)
|
||||
object_id = models.PositiveIntegerField(null=True, default=None)
|
||||
@@ -181,8 +178,7 @@ class Role(models.Model):
|
||||
return self.ancestors.filter(pk=accessor.pk).exists()
|
||||
else:
|
||||
accessor_type = ContentType.objects.get_for_model(accessor)
|
||||
roles = Role.objects.filter(content_type__pk=accessor_type.id,
|
||||
object_id=accessor.id)
|
||||
roles = Role.objects.filter(content_type__pk=accessor_type.id, object_id=accessor.id)
|
||||
return self.ancestors.filter(pk__in=roles).exists()
|
||||
|
||||
@property
|
||||
@@ -214,12 +210,12 @@ class Role(models.Model):
|
||||
|
||||
@staticmethod
|
||||
def rebuild_role_ancestor_list(additions, removals):
|
||||
'''
|
||||
"""
|
||||
Updates our `ancestors` map to accurately reflect all of the ancestors for a role
|
||||
|
||||
You should never need to call this. Signal handlers should be calling
|
||||
this method when the role hierachy changes automatically.
|
||||
'''
|
||||
"""
|
||||
# The ancestry table
|
||||
# =================================================
|
||||
#
|
||||
@@ -320,8 +316,7 @@ class Role(models.Model):
|
||||
# to the magic number of 41496, or 40000 for a nice round number
|
||||
def split_ids_for_sqlite(role_ids):
|
||||
for i in range(0, len(role_ids), 40000):
|
||||
yield role_ids[i:i + 40000]
|
||||
|
||||
yield role_ids[i : i + 40000]
|
||||
|
||||
with transaction.atomic():
|
||||
while len(additions) > 0 or len(removals) > 0:
|
||||
@@ -333,7 +328,8 @@ class Role(models.Model):
|
||||
if len(removals) > 0:
|
||||
for ids in split_ids_for_sqlite(removals):
|
||||
sql_params['ids'] = ','.join(str(x) for x in ids)
|
||||
cursor.execute('''
|
||||
cursor.execute(
|
||||
'''
|
||||
DELETE FROM %(ancestors_table)s
|
||||
WHERE descendent_id IN (%(ids)s)
|
||||
AND descendent_id != ancestor_id
|
||||
@@ -345,7 +341,9 @@ class Role(models.Model):
|
||||
WHERE parents.from_role_id = %(ancestors_table)s.descendent_id
|
||||
AND %(ancestors_table)s.ancestor_id = inner_ancestors.ancestor_id
|
||||
)
|
||||
''' % sql_params)
|
||||
'''
|
||||
% sql_params
|
||||
)
|
||||
|
||||
delete_ct += cursor.rowcount
|
||||
|
||||
@@ -353,7 +351,8 @@ class Role(models.Model):
|
||||
if len(additions) > 0:
|
||||
for ids in split_ids_for_sqlite(additions):
|
||||
sql_params['ids'] = ','.join(str(x) for x in ids)
|
||||
cursor.execute('''
|
||||
cursor.execute(
|
||||
'''
|
||||
INSERT INTO %(ancestors_table)s (descendent_id, ancestor_id, role_field, content_type_id, object_id)
|
||||
SELECT from_id, to_id, new_ancestry_list.role_field, new_ancestry_list.content_type_id, new_ancestry_list.object_id FROM (
|
||||
SELECT roles.id from_id,
|
||||
@@ -383,7 +382,9 @@ class Role(models.Model):
|
||||
AND %(ancestors_table)s.ancestor_id = new_ancestry_list.to_id
|
||||
)
|
||||
|
||||
''' % sql_params)
|
||||
'''
|
||||
% sql_params
|
||||
)
|
||||
insert_ct += cursor.rowcount
|
||||
|
||||
if insert_ct == 0 and delete_ct == 0:
|
||||
@@ -405,7 +406,6 @@ class Role(models.Model):
|
||||
new_removals.update([row[0] for row in cursor.fetchall()])
|
||||
removals = list(new_removals)
|
||||
|
||||
|
||||
@staticmethod
|
||||
def visible_roles(user):
|
||||
return Role.filter_visible_roles(user, Role.objects.all())
|
||||
@@ -413,19 +413,21 @@ class Role(models.Model):
|
||||
@staticmethod
|
||||
@check_singleton
|
||||
def filter_visible_roles(user, roles_qs):
|
||||
'''
|
||||
"""
|
||||
Visible roles include all roles that are ancestors of any
|
||||
roles that the user has access to.
|
||||
Case in point - organization auditor_role must see all roles
|
||||
in their organization, but some of those roles descend from
|
||||
organization admin_role, but not auditor_role.
|
||||
'''
|
||||
"""
|
||||
return roles_qs.filter(
|
||||
id__in=RoleAncestorEntry.objects.filter(
|
||||
descendent__in=RoleAncestorEntry.objects.filter(
|
||||
ancestor_id__in=list(user.roles.values_list('id', flat=True))
|
||||
).values_list('descendent', flat=True)
|
||||
).distinct().values_list('ancestor', flat=True)
|
||||
descendent__in=RoleAncestorEntry.objects.filter(ancestor_id__in=list(user.roles.values_list('id', flat=True))).values_list(
|
||||
'descendent', flat=True
|
||||
)
|
||||
)
|
||||
.distinct()
|
||||
.values_list('ancestor', flat=True)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
@@ -441,30 +443,29 @@ class Role(models.Model):
|
||||
|
||||
|
||||
class RoleAncestorEntry(models.Model):
|
||||
|
||||
class Meta:
|
||||
app_label = 'main'
|
||||
verbose_name_plural = _('role_ancestors')
|
||||
db_table = 'main_rbac_role_ancestors'
|
||||
index_together = [
|
||||
("ancestor", "content_type_id", "object_id"), # used by get_roles_on_resource
|
||||
("ancestor", "content_type_id", "role_field"), # used by accessible_objects
|
||||
("ancestor", "descendent"), # used by rebuild_role_ancestor_list in the NOT EXISTS clauses.
|
||||
("ancestor", "content_type_id", "object_id"), # used by get_roles_on_resource
|
||||
("ancestor", "content_type_id", "role_field"), # used by accessible_objects
|
||||
("ancestor", "descendent"), # used by rebuild_role_ancestor_list in the NOT EXISTS clauses.
|
||||
]
|
||||
|
||||
descendent = models.ForeignKey(Role, null=False, on_delete=models.CASCADE, related_name='+')
|
||||
ancestor = models.ForeignKey(Role, null=False, on_delete=models.CASCADE, related_name='+')
|
||||
role_field = models.TextField(null=False)
|
||||
descendent = models.ForeignKey(Role, null=False, on_delete=models.CASCADE, related_name='+')
|
||||
ancestor = models.ForeignKey(Role, null=False, on_delete=models.CASCADE, related_name='+')
|
||||
role_field = models.TextField(null=False)
|
||||
content_type_id = models.PositiveIntegerField(null=False)
|
||||
object_id = models.PositiveIntegerField(null=False)
|
||||
object_id = models.PositiveIntegerField(null=False)
|
||||
|
||||
|
||||
def get_roles_on_resource(resource, accessor):
|
||||
'''
|
||||
"""
|
||||
Returns a string list of the roles a accessor has for a given resource.
|
||||
An accessor can be either a User, Role, or an arbitrary resource that
|
||||
contains one or more Roles associated with it.
|
||||
'''
|
||||
"""
|
||||
|
||||
if type(accessor) == User:
|
||||
roles = accessor.roles.all()
|
||||
@@ -472,16 +473,15 @@ def get_roles_on_resource(resource, accessor):
|
||||
roles = [accessor]
|
||||
else:
|
||||
accessor_type = ContentType.objects.get_for_model(accessor)
|
||||
roles = Role.objects.filter(content_type__pk=accessor_type.id,
|
||||
object_id=accessor.id)
|
||||
roles = Role.objects.filter(content_type__pk=accessor_type.id, object_id=accessor.id)
|
||||
|
||||
return [
|
||||
role_field for role_field in
|
||||
RoleAncestorEntry.objects.filter(
|
||||
ancestor__in=roles,
|
||||
content_type_id=ContentType.objects.get_for_model(resource).id,
|
||||
object_id=resource.id
|
||||
).values_list('role_field', flat=True).distinct()
|
||||
role_field
|
||||
for role_field in RoleAncestorEntry.objects.filter(
|
||||
ancestor__in=roles, content_type_id=ContentType.objects.get_for_model(resource).id, object_id=resource.id
|
||||
)
|
||||
.values_list('role_field', flat=True)
|
||||
.distinct()
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user