From 5b3b4b48c0dc429a451ad753299a6857a43da52b Mon Sep 17 00:00:00 2001 From: Matthew Jones Date: Thu, 28 May 2015 15:59:08 -0400 Subject: [PATCH] Fix an issue when creating scan job templates where we weren't obeying the license flag, so folks could still create scan jobs even if they weren't enabled by the license. Plus Unit Tests --- awx/api/views.py | 1 + awx/main/access.py | 13 ++++++++++++- awx/main/tests/base.py | 5 +++-- awx/main/tests/jobs/jobs_monolithic.py | 5 +++++ 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/awx/api/views.py b/awx/api/views.py index 287d44cad1..df0c00061e 100644 --- a/awx/api/views.py +++ b/awx/api/views.py @@ -1681,6 +1681,7 @@ class JobTemplateList(ListCreateAPIView): model = JobTemplate serializer_class = JobTemplateSerializer + always_allow_superuser = False class JobTemplateDetail(RetrieveUpdateDestroyAPIView): diff --git a/awx/main/access.py b/awx/main/access.py index 5a609658ea..a63063469a 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -17,6 +17,7 @@ from rest_framework.exceptions import ParseError, PermissionDenied # AWX from awx.main.utils import * # noqa from awx.main.models import * # noqa +from awx.api.license import LicenseForbids from awx.main.task_engine import TaskSerializer __all__ = ['get_user_queryset', 'check_user_access'] @@ -145,7 +146,7 @@ class BaseAccess(object): def can_unattach(self, obj, sub_obj, relationship): return self.can_change(obj, None) - def check_license(self, add_host=False): + def check_license(self, add_host=False, feature=None): reader = TaskSerializer() validation_info = reader.from_file() if ('test' in sys.argv or 'jenkins' in sys.argv) and not os.environ.get('SKIP_LICENSE_FIXUP_FOR_TEST', ''): @@ -167,6 +168,12 @@ class BaseAccess(object): elif not add_host and free_instances < 0: raise PermissionDenied("host count exceeds available instances") + if feature is not None: + if "features" in validation_info and not validation_info["features"].get(feature, False): + raise LicenseForbids("Feature %s is not enabled in the active license" % feature) + elif "features" not in validation_info: + raise LicenseForbids("Features not found in active license") + class UserAccess(BaseAccess): ''' @@ -914,6 +921,10 @@ class JobTemplateAccess(BaseAccess): ''' if not data or '_method' in data: # So the browseable API will work? return True + + if 'job_type' in data and data['job_type'] == PERM_INVENTORY_SCAN: + self.check_license(feature='system_tracking') + if self.user.is_superuser: return True diff --git a/awx/main/tests/base.py b/awx/main/tests/base.py index f98fdef2dc..c9dbd34c2b 100644 --- a/awx/main/tests/base.py +++ b/awx/main/tests/base.py @@ -173,14 +173,15 @@ class BaseTestMixin(QueueTestMixin, MockCommonlySlowTestMixin): rnd_str = '____' + str(random.randint(1, 9999999)) return __name__ + '-generated-' + string + rnd_str - def create_test_license_file(self, instance_count=10000, license_date=int(time.time() + 3600)): + def create_test_license_file(self, instance_count=10000, license_date=int(time.time() + 3600), features=None): writer = LicenseWriter( company_name='AWX', contact_name='AWX Admin', contact_email='awx@example.com', license_date=license_date, instance_count=instance_count, - license_type='enterprise') + license_type='enterprise', + features=features) handle, license_path = tempfile.mkstemp(suffix='.json') os.close(handle) writer.write_file(license_path) diff --git a/awx/main/tests/jobs/jobs_monolithic.py b/awx/main/tests/jobs/jobs_monolithic.py index 559b952e14..bb2b2cfd58 100644 --- a/awx/main/tests/jobs/jobs_monolithic.py +++ b/awx/main/tests/jobs/jobs_monolithic.py @@ -429,6 +429,11 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase): job_type = PERM_INVENTORY_SCAN, inventory = self.inv_eng.pk, ) + # Without the system tracking license feature even super users can't create scan jobs + with self.current_user(self.user_sue): + data['credential'] = self.cred_sue.pk + response = self.post(url, data, expect=402) + self.create_test_license_file(features=dict(system_tracking=True)) # Regular users, even those who have access to the inv and cred can't create scan jobs templates with self.current_user(self.user_doug): data['credential'] = self.cred_doug.pk