mirror of
https://github.com/ansible/awx.git
synced 2026-05-19 14:57:39 -02:30
Enable deletion of orphaned approval nodes
Update serializer to include workflow approval for activity stream
This commit is contained in:
@@ -3456,13 +3456,13 @@ class WorkflowApprovalTemplateSerializer(UnifiedJobTemplateSerializer):
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
# class WorkflowJobTemplateApprovalSerializer(UnifiedJobTemplateSerializer):
|
class WorkflowJobTemplateApprovalSerializer(UnifiedJobTemplateSerializer):
|
||||||
# class Meta:
|
class Meta:
|
||||||
# model = WorkflowJobTemplateApproval
|
model = WorkflowApprovalTemplate
|
||||||
# fields = ('*',)
|
fields = ('*',)
|
||||||
#
|
|
||||||
# def post(self, obj):
|
def post(self, obj):
|
||||||
# return # POST only!!!
|
return # POST only!!!
|
||||||
|
|
||||||
|
|
||||||
class LaunchConfigurationBaseSerializer(BaseSerializer):
|
class LaunchConfigurationBaseSerializer(BaseSerializer):
|
||||||
@@ -4746,7 +4746,8 @@ class ActivityStreamSerializer(BaseSerializer):
|
|||||||
('o_auth2_access_token', ('id', 'user_id', 'description', 'application_id', 'scope')),
|
('o_auth2_access_token', ('id', 'user_id', 'description', 'application_id', 'scope')),
|
||||||
('o_auth2_application', ('id', 'name', 'description')),
|
('o_auth2_application', ('id', 'name', 'description')),
|
||||||
('credential_type', ('id', 'name', 'description', 'kind', 'managed_by_tower')),
|
('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
|
return field_list
|
||||||
|
|
||||||
@@ -4855,6 +4856,7 @@ class ActivityStreamSerializer(BaseSerializer):
|
|||||||
def _summarize_parent_ujt(self, obj, fk, summary_fields):
|
def _summarize_parent_ujt(self, obj, fk, summary_fields):
|
||||||
summary_keys = {'job': 'job_template',
|
summary_keys = {'job': 'job_template',
|
||||||
'workflow_job_template_node': 'workflow_job_template',
|
'workflow_job_template_node': 'workflow_job_template',
|
||||||
|
'workflow_approval': 'workflow_approval_template',
|
||||||
'schedule': 'unified_job_template'}
|
'schedule': 'unified_job_template'}
|
||||||
if fk not in summary_keys:
|
if fk not in summary_keys:
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -839,8 +839,6 @@ class SystemJobEventsList(SubListAPIView):
|
|||||||
return super(SystemJobEventsList, self).finalize_response(request, response, *args, **kwargs)
|
return super(SystemJobEventsList, self).finalize_response(request, response, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectUpdateCancel(RetrieveAPIView):
|
class ProjectUpdateCancel(RetrieveAPIView):
|
||||||
|
|
||||||
model = models.ProjectUpdate
|
model = models.ProjectUpdate
|
||||||
|
|||||||
@@ -2631,6 +2631,7 @@ class ActivityStreamAccess(BaseAccess):
|
|||||||
app_set = OAuth2ApplicationAccess(self.user).filtered_queryset()
|
app_set = OAuth2ApplicationAccess(self.user).filtered_queryset()
|
||||||
token_set = OAuth2TokenAccess(self.user).filtered_queryset()
|
token_set = OAuth2TokenAccess(self.user).filtered_queryset()
|
||||||
|
|
||||||
|
# &&&&&& Activity Stream + RBAC here??
|
||||||
return qs.filter(
|
return qs.filter(
|
||||||
Q(ad_hoc_command__inventory__in=inventory_set) |
|
Q(ad_hoc_command__inventory__in=inventory_set) |
|
||||||
Q(o_auth2_application__in=app_set) |
|
Q(o_auth2_application__in=app_set) |
|
||||||
@@ -2796,11 +2797,11 @@ class WorkflowApprovalAccess(BaseAccess):
|
|||||||
self.user, 'read_role'))
|
self.user, 'read_role'))
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return super(UnifiedJobTemplateAccess, self).get_queryset().exclude(
|
return super(WorkflowApprovalAccess, self).get_queryset().exclude(
|
||||||
workflowapprovaltemplate__isnull=False)
|
workflow_approval_template__isnull=False)
|
||||||
|
|
||||||
def can_approve_or_deny(self, obj):
|
def can_approve_or_deny(self, obj):
|
||||||
if self.user.approval_role:
|
if self.user.approval_role or self.user.system_administrator:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@@ -2828,8 +2829,8 @@ class WorkflowApprovalTemplateAccess(BaseAccess):
|
|||||||
self.user, 'read_role'))
|
self.user, 'read_role'))
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return super(UnifiedJobAccess, self).get_queryset().exclude(
|
return super(WorkflowApprovalTemplateAccess, self).get_queryset().filter(
|
||||||
workflowapproval__isnull=False)
|
approvals__isnull=False)
|
||||||
|
|
||||||
|
|
||||||
for cls in BaseAccess.__subclasses__():
|
for cls in BaseAccess.__subclasses__():
|
||||||
|
|||||||
@@ -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
|
import awx.main.fields
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
@@ -8,7 +8,7 @@ import django.db.models.deletion
|
|||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('main', '0082_v360_workflowapproval'),
|
('main', '0082_v360_webhook_http_method'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
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'),
|
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',
|
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(
|
migrations.CreateModel(
|
||||||
name='WorkflowApproval',
|
name='WorkflowApproval',
|
||||||
fields=[
|
fields=[
|
||||||
@@ -40,4 +50,14 @@ class Migration(migrations.Migration):
|
|||||||
],
|
],
|
||||||
bases=('main.unifiedjob',),
|
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'),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ activity_stream_registrar.connect(WorkflowJobTemplate)
|
|||||||
activity_stream_registrar.connect(WorkflowJobTemplateNode)
|
activity_stream_registrar.connect(WorkflowJobTemplateNode)
|
||||||
activity_stream_registrar.connect(WorkflowJob)
|
activity_stream_registrar.connect(WorkflowJob)
|
||||||
activity_stream_registrar.connect(WorkflowApproval)
|
activity_stream_registrar.connect(WorkflowApproval)
|
||||||
activity_stream_registrar.connect(WorkflowApprovalTemplate)
|
# activity_stream_registrar.connect(WorkflowApprovalTemplate)
|
||||||
activity_stream_registrar.connect(OAuth2Application)
|
activity_stream_registrar.connect(OAuth2Application)
|
||||||
activity_stream_registrar.connect(OAuth2AccessToken)
|
activity_stream_registrar.connect(OAuth2AccessToken)
|
||||||
|
|
||||||
|
|||||||
@@ -66,9 +66,8 @@ class ActivityStream(models.Model):
|
|||||||
workflow_job_node = models.ManyToManyField("WorkflowJobNode", blank=True)
|
workflow_job_node = models.ManyToManyField("WorkflowJobNode", blank=True)
|
||||||
workflow_job_template = models.ManyToManyField("WorkflowJobTemplate", blank=True)
|
workflow_job_template = models.ManyToManyField("WorkflowJobTemplate", blank=True)
|
||||||
workflow_job = models.ManyToManyField("WorkflowJob", 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_template = models.ManyToManyField("WorkflowApprovalTemplate", blank=True)
|
workflow_approval = models.ManyToManyField("WorkflowApproval", 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_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+')
|
unified_job = models.ManyToManyField("UnifiedJob", blank=True, related_name='activity_stream_as_unified_job+')
|
||||||
ad_hoc_command = models.ManyToManyField("AdHocCommand", blank=True)
|
ad_hoc_command = models.ManyToManyField("AdHocCommand", blank=True)
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ from awx.main.models import (
|
|||||||
InventorySource, InventoryUpdateEvent, Job, JobEvent, JobHostSummary,
|
InventorySource, InventoryUpdateEvent, Job, JobEvent, JobHostSummary,
|
||||||
JobTemplate, OAuth2AccessToken, Organization, Project, ProjectUpdateEvent,
|
JobTemplate, OAuth2AccessToken, Organization, Project, ProjectUpdateEvent,
|
||||||
Role, SystemJob, SystemJobEvent, SystemJobTemplate, UnifiedJob,
|
Role, SystemJob, SystemJobEvent, SystemJobTemplate, UnifiedJob,
|
||||||
UnifiedJobTemplate, User, UserSessionMembership,
|
UnifiedJobTemplate, User, UserSessionMembership, WorkflowJobTemplateNode,
|
||||||
ROLE_SINGLETON_SYSTEM_ADMINISTRATOR
|
WorkflowApprovalTemplate, ROLE_SINGLETON_SYSTEM_ADMINISTRATOR
|
||||||
)
|
)
|
||||||
from awx.main.constants import CENSOR_VALUE
|
from awx.main.constants import CENSOR_VALUE
|
||||||
from awx.main.utils import model_instance_diff, model_to_dict, camelcase_to_underscore, get_current_apps
|
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.WorkflowJobTemplate: serializers.WorkflowJobTemplateWithSpecSerializer,
|
||||||
models.WorkflowJobTemplateNode: serializers.WorkflowJobTemplateNodeSerializer,
|
models.WorkflowJobTemplateNode: serializers.WorkflowJobTemplateNodeSerializer,
|
||||||
models.WorkflowApproval: serializers.WorkflowApprovalSerializer,
|
models.WorkflowApproval: serializers.WorkflowApprovalSerializer,
|
||||||
models.WorkflowApprovalTemplate: serializers.WorkflowApprovalTemplateSerializer, # &&&&&&
|
models.WorkflowApprovalTemplate: serializers.WorkflowApprovalTemplateSerializer,
|
||||||
models.WorkflowJob: serializers.WorkflowJobSerializer,
|
models.WorkflowJob: serializers.WorkflowJobSerializer,
|
||||||
models.OAuth2AccessToken: serializers.OAuth2TokenSerializer,
|
models.OAuth2AccessToken: serializers.OAuth2TokenSerializer,
|
||||||
models.OAuth2Application: serializers.OAuth2ApplicationSerializer,
|
models.OAuth2Application: serializers.OAuth2ApplicationSerializer,
|
||||||
@@ -506,11 +506,6 @@ def activity_stream_update(sender, instance, **kwargs):
|
|||||||
activity_entry.setting = conf_to_dict(instance)
|
activity_entry.setting = conf_to_dict(instance)
|
||||||
activity_entry.save()
|
activity_entry.save()
|
||||||
|
|
||||||
# &&&&&&
|
|
||||||
# if isinstance(obj1, WorkflowApprovalTemplate) or isinstance(obj2_actual, WorkflowApprovalTemplate):
|
|
||||||
# continue
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def activity_stream_delete(sender, instance, **kwargs):
|
def activity_stream_delete(sender, instance, **kwargs):
|
||||||
if not activity_stream_enabled:
|
if not activity_stream_enabled:
|
||||||
@@ -645,23 +640,23 @@ def delete_inventory_for_org(sender, instance, **kwargs):
|
|||||||
logger.debug(e)
|
logger.debug(e)
|
||||||
|
|
||||||
|
|
||||||
# &&&&&& Placeholder code below for approval node deletion.
|
@receiver(pre_delete, sender=WorkflowJobTemplateNode)
|
||||||
# @receiver(pre_delete, sender=Job)
|
def delete_approval_nodes(sender, instance, **kwargs):
|
||||||
# def delete_detached_approval_nodes(sender, instance, **kwargs):
|
if type(instance.unified_job_template) is WorkflowApprovalTemplate:
|
||||||
# for l in instance.labels.all():
|
instance.unified_job_template.delete()
|
||||||
# if l.is_candidate_for_detach():
|
|
||||||
# l.delete()
|
|
||||||
#
|
# When setting UJT to anything other than "is approval node" - update this comment!
|
||||||
#
|
@receiver(pre_save, sender=WorkflowJobTemplateNode)
|
||||||
# @receiver(pre_delete, sender=Organization)
|
def placeholder_name(sender, instance, **kwargs):
|
||||||
# def delete_detached_approval_nodes(sender, instance, **kwargs):
|
try:
|
||||||
# approval_node = ???
|
old = WorkflowJobTemplateNode.objects.get(id=instance.id)
|
||||||
# user = get_current_user_or_none()
|
except sender.DoesNotExist:
|
||||||
# for node in approval_node:
|
return
|
||||||
# try:
|
if old.unified_job_template == instance.unified_job_template:
|
||||||
# node.schedule_deletion(user_id=getattr(user, 'id', None))
|
return
|
||||||
# except RuntimeError as e:
|
if type(old.unified_job_template) is WorkflowApprovalTemplate:
|
||||||
# logger.debug(e)
|
old.unified_job_template.delete()
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=Session)
|
@receiver(post_save, sender=Session)
|
||||||
|
|||||||
Reference in New Issue
Block a user