mirror of
https://github.com/ansible/awx.git
synced 2026-04-14 06:29:25 -02:30
Merge pull request #3005 from matburt/delete_protection
Add delete protection from certain objects
This commit is contained in:
@@ -2189,9 +2189,6 @@ class JobTemplateDetail(RetrieveUpdateDestroyAPIView):
|
|||||||
can_delete = request.user.can_access(JobTemplate, 'delete', obj)
|
can_delete = request.user.can_access(JobTemplate, 'delete', obj)
|
||||||
if not can_delete:
|
if not can_delete:
|
||||||
raise PermissionDenied("Cannot delete job template.")
|
raise PermissionDenied("Cannot delete job template.")
|
||||||
if obj.jobs.filter(status__in=['new', 'pending', 'waiting', 'running']).exists():
|
|
||||||
return Response({"error": "Delete not allowed while there are jobs running"},
|
|
||||||
status=status.HTTP_405_METHOD_NOT_ALLOWED)
|
|
||||||
return super(JobTemplateDetail, self).destroy(request, *args, **kwargs)
|
return super(JobTemplateDetail, self).destroy(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,11 +12,12 @@ from django.contrib.auth.models import User
|
|||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
|
||||||
# Django REST Framework
|
# Django REST Framework
|
||||||
from rest_framework.exceptions import ParseError, PermissionDenied
|
from rest_framework.exceptions import ParseError, PermissionDenied, ValidationError
|
||||||
|
|
||||||
# AWX
|
# AWX
|
||||||
from awx.main.utils import * # noqa
|
from awx.main.utils import * # noqa
|
||||||
from awx.main.models import * # noqa
|
from awx.main.models import * # noqa
|
||||||
|
from awx.main.models.unified_jobs import ACTIVE_STATES
|
||||||
from awx.main.models.mixins import ResourceMixin
|
from awx.main.models.mixins import ResourceMixin
|
||||||
from awx.api.license import LicenseForbids
|
from awx.api.license import LicenseForbids
|
||||||
from awx.main.task_engine import TaskSerializer
|
from awx.main.task_engine import TaskSerializer
|
||||||
@@ -310,7 +311,16 @@ class OrganizationAccess(BaseAccess):
|
|||||||
|
|
||||||
def can_delete(self, obj):
|
def can_delete(self, obj):
|
||||||
self.check_license(feature='multiple_organizations', check_expiration=False)
|
self.check_license(feature='multiple_organizations', check_expiration=False)
|
||||||
return self.can_change(obj, None)
|
is_change_possible = self.can_change(obj, None)
|
||||||
|
if not is_change_possible:
|
||||||
|
return False
|
||||||
|
active_jobs = []
|
||||||
|
active_jobs.extend(Job.objects.filter(project__in=obj.projects.all(), status__in=ACTIVE_STATES))
|
||||||
|
active_jobs.extend(ProjectUpdate.objects.filter(project__in=obj.projects.all(), status__in=ACTIVE_STATES))
|
||||||
|
active_jobs.extend(InventoryUpdate.objects.filter(inventory_source__inventory__organization=obj, status__in=ACTIVE_STATES))
|
||||||
|
if len(active_jobs) > 0:
|
||||||
|
raise ValidationError("Delete not allowed while there are jobs running. Number of jobs {}".format(len(active_jobs)))
|
||||||
|
return True
|
||||||
|
|
||||||
class InventoryAccess(BaseAccess):
|
class InventoryAccess(BaseAccess):
|
||||||
'''
|
'''
|
||||||
@@ -373,7 +383,15 @@ class InventoryAccess(BaseAccess):
|
|||||||
return self.user in obj.admin_role
|
return self.user in obj.admin_role
|
||||||
|
|
||||||
def can_delete(self, obj):
|
def can_delete(self, obj):
|
||||||
return self.can_admin(obj, None)
|
is_can_admin = self.can_admin(obj, None)
|
||||||
|
if not is_can_admin:
|
||||||
|
return False
|
||||||
|
active_jobs = []
|
||||||
|
active_jobs.extend(Job.objects.filter(inventory=obj, status__in=ACTIVE_STATES))
|
||||||
|
active_jobs.extend(InventoryUpdate.objects.filter(inventory_source__inventory=obj, status__in=ACTIVE_STATES))
|
||||||
|
if len(active_jobs) > 0:
|
||||||
|
raise ValidationError("Delete not allowed while there are jobs running. Number of jobs {}".format(len(active_jobs)))
|
||||||
|
return True
|
||||||
|
|
||||||
def can_run_ad_hoc_commands(self, obj):
|
def can_run_ad_hoc_commands(self, obj):
|
||||||
return self.user in obj.adhoc_role
|
return self.user in obj.adhoc_role
|
||||||
@@ -486,7 +504,14 @@ class GroupAccess(BaseAccess):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def can_delete(self, obj):
|
def can_delete(self, obj):
|
||||||
return obj and self.user in obj.inventory.admin_role
|
is_delete_allowed = bool(obj and self.user in obj.inventory.admin_role)
|
||||||
|
if not is_delete_allowed:
|
||||||
|
return False
|
||||||
|
active_jobs = []
|
||||||
|
active_jobs.extend(InventoryUpdate.objects.filter(inventory_source__in=obj.inventory_sources.all(), status__in=ACTIVE_STATES))
|
||||||
|
if len(active_jobs) > 0:
|
||||||
|
raise ValidationError("Delete not allowed while there are jobs running. Number of jobs {}".format(len(active_jobs)))
|
||||||
|
return True
|
||||||
|
|
||||||
class InventorySourceAccess(BaseAccess):
|
class InventorySourceAccess(BaseAccess):
|
||||||
'''
|
'''
|
||||||
@@ -736,7 +761,15 @@ class ProjectAccess(BaseAccess):
|
|||||||
return self.user in obj.admin_role
|
return self.user in obj.admin_role
|
||||||
|
|
||||||
def can_delete(self, obj):
|
def can_delete(self, obj):
|
||||||
return self.can_change(obj, None)
|
is_change_allowed = self.can_change(obj, None)
|
||||||
|
if not is_change_allowed:
|
||||||
|
return False
|
||||||
|
active_jobs = []
|
||||||
|
active_jobs.extend(Job.objects.filter(project=obj, status__in=ACTIVE_STATES))
|
||||||
|
active_jobs.extend(ProjectUpdate.objects.filter(project=obj, status__in=ACTIVE_STATES))
|
||||||
|
if len(active_jobs) > 0:
|
||||||
|
raise ValidationError("Delete not allowed while there are jobs running. Number of jobs {}".format(len(active_jobs)))
|
||||||
|
return True
|
||||||
|
|
||||||
@check_superuser
|
@check_superuser
|
||||||
def can_start(self, obj):
|
def can_start(self, obj):
|
||||||
@@ -958,7 +991,13 @@ class JobTemplateAccess(BaseAccess):
|
|||||||
|
|
||||||
@check_superuser
|
@check_superuser
|
||||||
def can_delete(self, obj):
|
def can_delete(self, obj):
|
||||||
return self.user in obj.admin_role
|
is_delete_allowed = self.user in obj.admin_role
|
||||||
|
if not is_delete_allowed:
|
||||||
|
return False
|
||||||
|
active_jobs = obj.jobs.filter(status__in=ACTIVE_STATES)
|
||||||
|
if len(active_jobs) > 0:
|
||||||
|
raise ValidationError("Delete not allowed while there are jobs running. Number of jobs {}".format(len(active_jobs)))
|
||||||
|
return True
|
||||||
|
|
||||||
class JobAccess(BaseAccess):
|
class JobAccess(BaseAccess):
|
||||||
'''
|
'''
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ __all__ = ['UnifiedJobTemplate', 'UnifiedJob']
|
|||||||
logger = logging.getLogger('awx.main.models.unified_jobs')
|
logger = logging.getLogger('awx.main.models.unified_jobs')
|
||||||
|
|
||||||
CAN_CANCEL = ('new', 'pending', 'waiting', 'running')
|
CAN_CANCEL = ('new', 'pending', 'waiting', 'running')
|
||||||
|
ACTIVE_STATES = CAN_CANCEL
|
||||||
|
|
||||||
|
|
||||||
class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique, NotificationFieldsModel):
|
class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique, NotificationFieldsModel):
|
||||||
|
|||||||
Reference in New Issue
Block a user