diff --git a/awx/api/serializers.py b/awx/api/serializers.py index f492b06ee9..47564414b1 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -37,6 +37,7 @@ from polymorphic import PolymorphicModel # AWX from awx.main.constants import SCHEDULEABLE_PROVIDERS from awx.main.models import * # noqa +from awx.main.access import get_user_capabilities from awx.main.fields import ImplicitRoleField from awx.main.utils import get_type_for_model, get_model_for_type, build_url, timestamp_apiformat, camelcase_to_underscore, getattrd from awx.main.conf import tower_settings @@ -330,12 +331,12 @@ class BaseSerializer(serializers.ModelSerializer): } if len(roles) > 0: summary_fields['object_roles'] = roles - if hasattr(obj, 'get_can_edit'): - request = self.context.get('request', None) - if request and request.user is not None: - summary_fields['can_edit'] = obj.get_can_edit(request.user) - elif hasattr(obj, 'can_edit'): - summary_fields['can_edit'] = obj.can_edit + view = self.context.get('view', None) + if view and view.request and view.request.user: + user_capabilities = get_user_capabilities(view.request.user, obj) + if user_capabilities: + summary_fields['user_capabilities'] = user_capabilities + return summary_fields def get_created(self, obj): diff --git a/awx/main/access.py b/awx/main/access.py index 5fa3b76274..b8505746df 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -116,6 +116,18 @@ def check_user_access(user, model_class, action, *args, **kwargs): return result return False +def get_user_capabilities(user, instance): + ''' + Returns a dictionary of capabilities the user has on the particular + instance. *NOTE* This is not a direct mapping of can_* methods into this + dictionary, it is intended to munge some queries in a way that is + convenient for the user interface to consume and hide or show various + actions in the interface. + ''' + for access_class in access_registry.get(type(instance), []): + return access_class(user).get_user_capabilities(instance) + return None + def check_superuser(func): ''' check_superuser is a decorator that provides a simple short circuit @@ -207,6 +219,33 @@ class BaseAccess(object): elif "features" not in validation_info: raise LicenseForbids("Features not found in active license.") + def get_user_capabilities(self, obj): + user_capabilities = {} + + if hasattr(obj, 'get_can_edit'): + user_capabilities['change'] = obj.get_can_edit(self.user) + elif hasattr(obj, 'can_edit'): + user_capabilities['change'] = obj.can_edit + + if isinstance(obj, JobTemplate): + user_capabilities['copy'] = self.user.can_access(type(obj), 'add', { 'reference_obj': obj }) + print(type(obj)) + + for method in ['change', 'delete', 'start']: + try: + if isinstance(obj, Group) and method is 'start' and obj.inventory_source: + obj = obj.inventory_source + + if method in ['change']: # 3 args + user_capabilities[method] = self.user.can_access(type(obj), method, obj, {}) + else: # 2 args + user_capabilities[method] = self.user.can_access(type(obj), method, obj) + except Exception as exc: + user_capabilities[method] = False + print(exc) + + return user_capabilities + class UserAccess(BaseAccess): '''