diff --git a/awx/api/filters.py b/awx/api/filters.py index d861303f1e..5146ff0cd2 100644 --- a/awx/api/filters.py +++ b/awx/api/filters.py @@ -19,6 +19,7 @@ from rest_framework.filters import BaseFilterBackend # Ansible Tower from awx.main.utils import get_type_for_model, to_python_boolean +from awx.main.models.rbac import RoleAncestorEntry class MongoFilterBackend(BaseFilterBackend): @@ -158,6 +159,7 @@ class FieldLookupBackend(BaseFilterBackend): and_filters = [] or_filters = [] chain_filters = [] + role_filters = [] for key, values in request.query_params.lists(): if key in self.RESERVED_NAMES: continue @@ -174,6 +176,11 @@ class FieldLookupBackend(BaseFilterBackend): key = key[:-5] q_int = True + # RBAC filtering + if key == 'role_level': + role_filters.append(values[0]) + continue + # Custom chain__ and or__ filters, mutually exclusive (both can # precede not__). q_chain = False @@ -204,13 +211,21 @@ class FieldLookupBackend(BaseFilterBackend): and_filters.append((q_not, new_key, value)) # Now build Q objects for database query filter. - if and_filters or or_filters or chain_filters: + if and_filters or or_filters or chain_filters or role_filters: args = [] for n, k, v in and_filters: if n: args.append(~Q(**{k:v})) else: args.append(Q(**{k:v})) + for role_name in role_filters: + args.append( + Q(pk__in=RoleAncestorEntry.objects.filter( + ancestor__in=request.user.roles.all(), + content_type_id=ContentType.objects.get_for_model(queryset.model).id, + role_field=role_name + ).values_list('object_id').distinct()) + ) if or_filters: q = Q() for n,k,v in or_filters: diff --git a/awx/api/templates/api/_list_common.md b/awx/api/templates/api/_list_common.md index e355421de3..36e6819276 100644 --- a/awx/api/templates/api/_list_common.md +++ b/awx/api/templates/api/_list_common.md @@ -132,3 +132,8 @@ values. Lists (for the `in` lookup) may be specified as a comma-separated list of values. + +(_Added in Ansible Tower 3.1.0_) Filtering based on the requesting user's +level of access by query string parameter. + +* `role_level`: Level of role to filter on, such as `admin_role`