mirror of
https://github.com/ZwareBear/awx.git
synced 2026-04-22 07:51:52 -05:00
Replaced our 'Resource' table with a GenericForeignKey in RolePermission
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
# Copyright (c) 2015 Ansible, Inc.
|
||||
# All Rights Reserved.
|
||||
|
||||
import traceback
|
||||
|
||||
# Django
|
||||
from django.db import connection
|
||||
from django.db.models.signals import (
|
||||
@@ -23,10 +25,10 @@ from django.db.transaction import TransactionManagementError
|
||||
|
||||
|
||||
# AWX
|
||||
from awx.main.models.rbac import Resource, RolePermission, Role
|
||||
from awx.main.models.rbac import RolePermission, Role
|
||||
|
||||
|
||||
__all__ = ['AutoOneToOneField', 'ImplicitResourceField', 'ImplicitRoleField']
|
||||
__all__ = ['AutoOneToOneField', 'ImplicitRoleField']
|
||||
|
||||
|
||||
# Based on AutoOneToOneField from django-annoying:
|
||||
@@ -59,53 +61,6 @@ class AutoOneToOneField(models.OneToOneField):
|
||||
|
||||
|
||||
|
||||
class ResourceFieldDescriptor(ReverseSingleRelatedObjectDescriptor):
|
||||
"""Descriptor for access to the object from its related class."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ResourceFieldDescriptor, self).__init__(*args, **kwargs)
|
||||
|
||||
def __get__(self, instance, instance_type=None):
|
||||
resource = super(ResourceFieldDescriptor, self).__get__(instance, instance_type)
|
||||
if resource:
|
||||
return resource
|
||||
if connection.needs_rollback:
|
||||
raise TransactionManagementError('Current transaction has failed, cannot create implicit resource')
|
||||
resource = Resource.objects.create(content_object=instance)
|
||||
setattr(instance, self.field.name, resource)
|
||||
if instance.pk:
|
||||
instance.save(update_fields=[self.field.name,])
|
||||
return resource
|
||||
|
||||
|
||||
class ImplicitResourceField(models.ForeignKey):
|
||||
"""Creates an associated resource object if one doesn't already exist"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs.setdefault('to', 'Resource')
|
||||
kwargs.setdefault('related_name', '+')
|
||||
kwargs.setdefault('null', 'True')
|
||||
super(ImplicitResourceField, self).__init__(*args, **kwargs)
|
||||
|
||||
def contribute_to_class(self, cls, name):
|
||||
super(ImplicitResourceField, self).contribute_to_class(cls, name)
|
||||
setattr(cls, self.name, ResourceFieldDescriptor(self))
|
||||
post_save.connect(self._post_save, cls, True)
|
||||
post_delete.connect(self._post_delete, cls, True)
|
||||
|
||||
def _post_save(self, instance, *args, **kwargs):
|
||||
# Ensures our resource object exists and that it's content_object
|
||||
# points back to our hosting instance.
|
||||
this_resource = getattr(instance, self.name)
|
||||
if not this_resource.object_id:
|
||||
this_resource.content_object = instance
|
||||
this_resource.save()
|
||||
|
||||
def _post_delete(self, instance, *args, **kwargs):
|
||||
getattr(instance, self.name).delete()
|
||||
|
||||
|
||||
|
||||
|
||||
def resolve_role_field(obj, field):
|
||||
ret = []
|
||||
@@ -153,9 +108,13 @@ class ImplicitRoleDescriptor(ReverseSingleRelatedObjectDescriptor):
|
||||
if connection.needs_rollback:
|
||||
raise TransactionManagementError('Current transaction has failed, cannot create implicit role')
|
||||
|
||||
role = Role.objects.create(name=self.role_name, description=self.role_description, content_object=instance)
|
||||
if self.parent_role:
|
||||
|
||||
role = Role.objects.create(name=self.role_name, description=self.role_description, content_object=instance)
|
||||
setattr(instance, self.field.name, role)
|
||||
if instance.pk:
|
||||
instance.save(update_fields=[self.field.name,])
|
||||
|
||||
if self.parent_role:
|
||||
# Add all non-null parent roles as parents
|
||||
paths = self.parent_role if type(self.parent_role) is list else [self.parent_role]
|
||||
for path in paths:
|
||||
@@ -165,14 +124,11 @@ class ImplicitRoleDescriptor(ReverseSingleRelatedObjectDescriptor):
|
||||
parents = resolve_role_field(instance, path)
|
||||
for parent in parents:
|
||||
role.parents.add(parent)
|
||||
setattr(instance, self.field.name, role)
|
||||
if instance.pk:
|
||||
instance.save(update_fields=[self.field.name,])
|
||||
|
||||
if self.permissions is not None:
|
||||
permissions = RolePermission(
|
||||
role=role,
|
||||
resource=instance.resource
|
||||
resource=instance
|
||||
)
|
||||
|
||||
if 'all' in self.permissions and self.permissions['all']:
|
||||
@@ -289,48 +245,29 @@ class ImplicitRoleField(models.ForeignKey):
|
||||
def _post_init(self, instance, *args, **kwargs):
|
||||
if not self.parent_role:
|
||||
return
|
||||
#if not hasattr(instance, self.name):
|
||||
# getattr(instance, self.name)
|
||||
|
||||
if not instance.pk:
|
||||
return
|
||||
|
||||
self._calc_original_parents(instance)
|
||||
|
||||
def _calc_original_parents(self, instance):
|
||||
if not hasattr(self, '__original_parent_roles'):
|
||||
setattr(self, '__original_parent_roles', []) # do not just self.__original_parent_roles=[], it's not the same here
|
||||
paths = self.parent_role if type(self.parent_role) is list else [self.parent_role]
|
||||
all_parents = set()
|
||||
original_parent_roles = set()
|
||||
for path in paths:
|
||||
if path.startswith("singleton:"):
|
||||
parents = [Role.singleton(path[10:])]
|
||||
else:
|
||||
parents = resolve_role_field(instance, path)
|
||||
for parent in parents:
|
||||
all_parents.add(parent)
|
||||
#role.parents.add(parent)
|
||||
self.__original_parent_roles = all_parents
|
||||
original_parent_roles.add(parent)
|
||||
setattr(self, '__original_parent_roles', original_parent_roles)
|
||||
|
||||
'''
|
||||
field_names = self.parent_role
|
||||
if type(field_names) is not list:
|
||||
field_names = [field_names]
|
||||
self.__original_values = {}
|
||||
for field_name in field_names:
|
||||
if field_name.startswith('singleton:'):
|
||||
continue
|
||||
first_field_name = field_name.split('.')[0]
|
||||
self.__original_values[first_field_name] = getattr(instance, first_field_name)
|
||||
'''
|
||||
else:
|
||||
print('WE DO NEED THIS')
|
||||
pass
|
||||
|
||||
def _post_save(self, instance, *args, **kwargs):
|
||||
def _post_save(self, instance, created, *args, **kwargs):
|
||||
# Ensure that our field gets initialized after our first save
|
||||
this_role = getattr(instance, self.name)
|
||||
if not this_role.object_id:
|
||||
# Ensure our ref back to our instance is set. This will not be set the
|
||||
# first time the object is saved because we create the role in our _post_init
|
||||
# but that happens before an id for the instance has been set (because it
|
||||
# hasn't been saved yet!). Now that everything has an id, we patch things
|
||||
# so the role references the instance.
|
||||
this_role.content_object = instance
|
||||
this_role.save()
|
||||
|
||||
# As object relations change, the role hierarchy might also change if the relations
|
||||
# that changed were referenced in our magic parent_role field. This code synchronizes
|
||||
@@ -338,8 +275,12 @@ class ImplicitRoleField(models.ForeignKey):
|
||||
if not self.parent_role:
|
||||
return
|
||||
|
||||
if created:
|
||||
self._calc_original_parents(instance)
|
||||
return
|
||||
|
||||
paths = self.parent_role if type(self.parent_role) is list else [self.parent_role]
|
||||
original_parents = self.__original_parent_roles
|
||||
original_parents = getattr(self, '__original_parent_roles')
|
||||
new_parents = set()
|
||||
for path in paths:
|
||||
if path.startswith("singleton:"):
|
||||
@@ -356,7 +297,7 @@ class ImplicitRoleField(models.ForeignKey):
|
||||
this_role.parents.add(role)
|
||||
Role.unpause_role_ancestor_rebuilding()
|
||||
|
||||
self.__original_parent_roles = new_parents
|
||||
setattr(self, '__original_parent_roles', new_parents)
|
||||
|
||||
def _post_delete(self, instance, *args, **kwargs):
|
||||
this_role = getattr(instance, self.name)
|
||||
|
||||
Reference in New Issue
Block a user