1
0
mirror of https://github.com/ansible/awx.git synced 2024-10-28 02:25:27 +03:00

Enable deletion of orphaned approval nodes

Update serializer to include workflow approval for activity stream
This commit is contained in:
beeankha 2019-07-25 15:03:26 -04:00 committed by Ryan Petrello
parent 64c94d478d
commit 3357c96774
No known key found for this signature in database
GPG Key ID: F2AA5F2122351777
7 changed files with 61 additions and 46 deletions

View File

@ -3456,13 +3456,13 @@ class WorkflowApprovalTemplateSerializer(UnifiedJobTemplateSerializer):
return res
# class WorkflowJobTemplateApprovalSerializer(UnifiedJobTemplateSerializer):
# class Meta:
# model = WorkflowJobTemplateApproval
# fields = ('*',)
#
# def post(self, obj):
# return # POST only!!!
class WorkflowJobTemplateApprovalSerializer(UnifiedJobTemplateSerializer):
class Meta:
model = WorkflowApprovalTemplate
fields = ('*',)
def post(self, obj):
return # POST only!!!
class LaunchConfigurationBaseSerializer(BaseSerializer):
@ -4746,7 +4746,8 @@ class ActivityStreamSerializer(BaseSerializer):
('o_auth2_access_token', ('id', 'user_id', 'description', 'application_id', 'scope')),
('o_auth2_application', ('id', 'name', 'description')),
('credential_type', ('id', 'name', 'description', 'kind', 'managed_by_tower')),
('ad_hoc_command', ('id', 'name', 'status', 'limit'))
('ad_hoc_command', ('id', 'name', 'status', 'limit')),
('workflow_approval', ('id', 'unified_job_id')),
]
return field_list
@ -4855,6 +4856,7 @@ class ActivityStreamSerializer(BaseSerializer):
def _summarize_parent_ujt(self, obj, fk, summary_fields):
summary_keys = {'job': 'job_template',
'workflow_job_template_node': 'workflow_job_template',
'workflow_approval': 'workflow_approval_template',
'schedule': 'unified_job_template'}
if fk not in summary_keys:
return

View File

@ -839,8 +839,6 @@ class SystemJobEventsList(SubListAPIView):
return super(SystemJobEventsList, self).finalize_response(request, response, *args, **kwargs)
class ProjectUpdateCancel(RetrieveAPIView):
model = models.ProjectUpdate

View File

@ -2631,6 +2631,7 @@ class ActivityStreamAccess(BaseAccess):
app_set = OAuth2ApplicationAccess(self.user).filtered_queryset()
token_set = OAuth2TokenAccess(self.user).filtered_queryset()
# &&&&&& Activity Stream + RBAC here??
return qs.filter(
Q(ad_hoc_command__inventory__in=inventory_set) |
Q(o_auth2_application__in=app_set) |
@ -2796,11 +2797,11 @@ class WorkflowApprovalAccess(BaseAccess):
self.user, 'read_role'))
def get_queryset(self):
return super(UnifiedJobTemplateAccess, self).get_queryset().exclude(
workflowapprovaltemplate__isnull=False)
return super(WorkflowApprovalAccess, self).get_queryset().exclude(
workflow_approval_template__isnull=False)
def can_approve_or_deny(self, obj):
if self.user.approval_role:
if self.user.approval_role or self.user.system_administrator:
return True
@ -2828,8 +2829,8 @@ class WorkflowApprovalTemplateAccess(BaseAccess):
self.user, 'read_role'))
def get_queryset(self):
return super(UnifiedJobAccess, self).get_queryset().exclude(
workflowapproval__isnull=False)
return super(WorkflowApprovalTemplateAccess, self).get_queryset().filter(
approvals__isnull=False)
for cls in BaseAccess.__subclasses__():

View File

@ -1,4 +1,4 @@
# Generated by Django 2.2.2 on 2019-07-18 14:12
# Generated by Django 2.2.2 on 2019-07-25 19:16
import awx.main.fields
from django.db import migrations, models
@ -8,7 +8,7 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('main', '0082_v360_workflowapproval'),
('main', '0082_v360_webhook_http_method'),
]
operations = [
@ -32,6 +32,16 @@ class Migration(migrations.Migration):
field=awx.main.fields.ImplicitRoleField(editable=False, null='True', on_delete=django.db.models.deletion.CASCADE, parent_role=['singleton:system_auditor', 'organization.approval_role', 'admin_role'], related_name='+', to='main.Role'),
preserve_default='True',
),
migrations.AlterField(
model_name='workflowjobnode',
name='unified_job_template',
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='workflowjobnodes', to='main.UnifiedJobTemplate'),
),
migrations.AlterField(
model_name='workflowjobtemplatenode',
name='unified_job_template',
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='workflowjobtemplatenodes', to='main.UnifiedJobTemplate'),
),
migrations.CreateModel(
name='WorkflowApproval',
fields=[
@ -40,4 +50,14 @@ class Migration(migrations.Migration):
],
bases=('main.unifiedjob',),
),
migrations.AddField(
model_name='activitystream',
name='workflow_approval',
field=models.ManyToManyField(blank=True, to='main.WorkflowApproval'),
),
migrations.AddField(
model_name='activitystream',
name='workflow_approval_template',
field=models.ManyToManyField(blank=True, to='main.WorkflowApprovalTemplate'),
),
]

View File

@ -203,7 +203,7 @@ activity_stream_registrar.connect(WorkflowJobTemplate)
activity_stream_registrar.connect(WorkflowJobTemplateNode)
activity_stream_registrar.connect(WorkflowJob)
activity_stream_registrar.connect(WorkflowApproval)
activity_stream_registrar.connect(WorkflowApprovalTemplate)
# activity_stream_registrar.connect(WorkflowApprovalTemplate)
activity_stream_registrar.connect(OAuth2Application)
activity_stream_registrar.connect(OAuth2AccessToken)

View File

@ -66,9 +66,8 @@ class ActivityStream(models.Model):
workflow_job_node = models.ManyToManyField("WorkflowJobNode", blank=True)
workflow_job_template = models.ManyToManyField("WorkflowJobTemplate", blank=True)
workflow_job = models.ManyToManyField("WorkflowJob", blank=True)
# Possibly adding workflow_approval-related fields here?? &&&&&&
# workflow_approval_template = models.ManyToManyField("WorkflowApprovalTemplate", blank=True)
# workflow_approval = models.ManyToManyField("WorkflowApproval", blank=True)
workflow_approval_template = models.ManyToManyField("WorkflowApprovalTemplate", blank=True)
workflow_approval = models.ManyToManyField("WorkflowApproval", blank=True)
unified_job_template = models.ManyToManyField("UnifiedJobTemplate", blank=True, related_name='activity_stream_as_unified_job_template+')
unified_job = models.ManyToManyField("UnifiedJob", blank=True, related_name='activity_stream_as_unified_job+')
ad_hoc_command = models.ManyToManyField("AdHocCommand", blank=True)

View File

@ -34,8 +34,8 @@ from awx.main.models import (
InventorySource, InventoryUpdateEvent, Job, JobEvent, JobHostSummary,
JobTemplate, OAuth2AccessToken, Organization, Project, ProjectUpdateEvent,
Role, SystemJob, SystemJobEvent, SystemJobTemplate, UnifiedJob,
UnifiedJobTemplate, User, UserSessionMembership,
ROLE_SINGLETON_SYSTEM_ADMINISTRATOR
UnifiedJobTemplate, User, UserSessionMembership, WorkflowJobTemplateNode,
WorkflowApprovalTemplate, ROLE_SINGLETON_SYSTEM_ADMINISTRATOR
)
from awx.main.constants import CENSOR_VALUE
from awx.main.utils import model_instance_diff, model_to_dict, camelcase_to_underscore, get_current_apps
@ -431,7 +431,7 @@ def model_serializer_mapping():
models.WorkflowJobTemplate: serializers.WorkflowJobTemplateWithSpecSerializer,
models.WorkflowJobTemplateNode: serializers.WorkflowJobTemplateNodeSerializer,
models.WorkflowApproval: serializers.WorkflowApprovalSerializer,
models.WorkflowApprovalTemplate: serializers.WorkflowApprovalTemplateSerializer, # &&&&&&
models.WorkflowApprovalTemplate: serializers.WorkflowApprovalTemplateSerializer,
models.WorkflowJob: serializers.WorkflowJobSerializer,
models.OAuth2AccessToken: serializers.OAuth2TokenSerializer,
models.OAuth2Application: serializers.OAuth2ApplicationSerializer,
@ -506,11 +506,6 @@ def activity_stream_update(sender, instance, **kwargs):
activity_entry.setting = conf_to_dict(instance)
activity_entry.save()
# &&&&&&
# if isinstance(obj1, WorkflowApprovalTemplate) or isinstance(obj2_actual, WorkflowApprovalTemplate):
# continue
def activity_stream_delete(sender, instance, **kwargs):
if not activity_stream_enabled:
@ -645,23 +640,23 @@ def delete_inventory_for_org(sender, instance, **kwargs):
logger.debug(e)
# &&&&&& Placeholder code below for approval node deletion.
# @receiver(pre_delete, sender=Job)
# def delete_detached_approval_nodes(sender, instance, **kwargs):
# for l in instance.labels.all():
# if l.is_candidate_for_detach():
# l.delete()
#
#
# @receiver(pre_delete, sender=Organization)
# def delete_detached_approval_nodes(sender, instance, **kwargs):
# approval_node = ???
# user = get_current_user_or_none()
# for node in approval_node:
# try:
# node.schedule_deletion(user_id=getattr(user, 'id', None))
# except RuntimeError as e:
# logger.debug(e)
@receiver(pre_delete, sender=WorkflowJobTemplateNode)
def delete_approval_nodes(sender, instance, **kwargs):
if type(instance.unified_job_template) is WorkflowApprovalTemplate:
instance.unified_job_template.delete()
# When setting UJT to anything other than "is approval node" - update this comment!
@receiver(pre_save, sender=WorkflowJobTemplateNode)
def placeholder_name(sender, instance, **kwargs):
try:
old = WorkflowJobTemplateNode.objects.get(id=instance.id)
except sender.DoesNotExist:
return
if old.unified_job_template == instance.unified_job_template:
return
if type(old.unified_job_template) is WorkflowApprovalTemplate:
old.unified_job_template.delete()
@receiver(post_save, sender=Session)