diff --git a/awx/main/models/__init__.py b/awx/main/models/__init__.py index 8b8cf114157e..8803842fd0ce 100644 --- a/awx/main/models/__init__.py +++ b/awx/main/models/__init__.py @@ -57,7 +57,6 @@ from awx.main.models.rbac import ( # noqa Role, batch_role_ancestor_rebuilding, - get_roles_on_resource, role_summary_fields_generator, ROLE_SINGLETON_SYSTEM_ADMINISTRATOR, ROLE_SINGLETON_SYSTEM_AUDITOR, diff --git a/awx/main/models/mixins.py b/awx/main/models/mixins.py index 75b304a32a08..3ab32ba81038 100644 --- a/awx/main/models/mixins.py +++ b/awx/main/models/mixins.py @@ -19,7 +19,7 @@ # AWX from awx.main.models.base import prevent_search -from awx.main.models.rbac import Role, RoleAncestorEntry, get_roles_on_resource +from awx.main.models.rbac import Role, RoleAncestorEntry from awx.main.utils import parse_yaml_or_json, get_custom_venv_choices, get_licenser, polymorphic from awx.main.utils.execution_environments import get_default_execution_environment from awx.main.utils.encryption import decrypt_value, get_encryption_key, is_encrypted @@ -54,10 +54,7 @@ def accessible_objects(cls, accessor, role_field): Use instead of `MyModel.objects` when you want to only consider resources that a user has specific permissions for. For example: MyModel.accessible_objects(user, 'read_role').filter(name__istartswith='bar'); - NOTE: This should only be used for list type things. If you have a - specific resource you want to check permissions on, it is more - performant to resolve the resource in question then call - `myresource.get_permissions(user)`. + NOTE: This should only be used for list type things. """ return ResourceMixin._accessible_objects(cls, accessor, role_field) @@ -86,15 +83,6 @@ def _accessible_pk_qs(cls, accessor, role_field, content_types=None): def _accessible_objects(cls, accessor, role_field): return cls.objects.filter(pk__in=ResourceMixin._accessible_pk_qs(cls, accessor, role_field)) - def get_permissions(self, 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. - """ - - return get_roles_on_resource(self, accessor) - class SurveyJobTemplateMixin(models.Model): class Meta: diff --git a/docs/rbac.md b/docs/rbac.md index f64bc2222331..25591f6cf9c0 100644 --- a/docs/rbac.md +++ b/docs/rbac.md @@ -95,6 +95,12 @@ The `singleton` class method is a helper method on the `Role` model that helps i You may use the `user in some_role` syntax to check and see if the specified user is a member of the given role, **or** a member of any ancestor role. +#### `get_roles_on_resource(resource, accessor)` + +This is a static method (not bound to a class) that will efficiently return the names +of all roles that the `accessor` (a user or a team) has on a particular resource. +The resource is a python object for something like an organization, credential, or job template. +Return value is a list of strings like `["admin_role", "execute_role"]`. ### Fields @@ -126,13 +132,17 @@ By mixing in the `ResourceMixin` to your model, you are turning your model in to objects.filter(name__istartswith='december') ``` -##### `get_permissions(self, user)` +##### `accessible_pk_qs(cls, user, role_field)` + +`accessible_pk_qs` returns a queryset of ids that match the same role filter as `accessible_objects`. +A key difference is that this is more performant to use in subqueries when filtering related models. -`get_permissions` is an instance method that will give you the list of role names that the user has access to for a given object. +Say that another model, `YourModel` has a ForeignKey reference to `MyModel` via a field `my_model`, +and you want to return all instances of `YourModel` that have a visible related `MyModel`. +The best way to do this is: ```python - >>> instance.get_permissions(admin) - ['admin_role', 'execute_role', 'read_role'] + YourModel.filter(my_model=MyModel.accessible_pk_qs(user, 'admin_role')) ``` ## Usage @@ -144,10 +154,7 @@ After exploring the _Overview_, the usage of the RBAC implementation in your cod class Document(Model, ResourceMixin): ... # declare your new role - readonly_role = ImplicitRoleField( - role_name="readonly", - permissions={'read':True}, - ) + readonly_role = ImplicitRoleField() ``` Now that your model is a resource and has a `Role` defined, you can begin to access the helper methods provided to you by the `ResourceMixin` for checking a user's access to your resource. Here is the output of a Python REPL session: @@ -156,11 +163,11 @@ Now that your model is a resource and has a `Role` defined, you can begin to acc # we've created some documents and a user >>> document = Document.objects.filter(pk=1) >>> user = User.objects.first() - >>> user in document.read_role + >>> user in document.readonly_role False # not accessible by default >>> document.readonly_role.members.add(user) - >>> user in document.read_role + >>> user in document.readonly_role True # now it is accessible - >>> user in document.admin_role + >>> user in document.readonly_role False # my role does not have admin permission ```