Repository: ansible/awx
File: awx/api/views/__init__.py (Python)

Code before:
    serializer_class = serializers.LabelSerializer
    parent_model = models.Job
    relationship = 'labels'
    resource_purpose = 'labels of a job'


class WorkflowJobLabelList(JobLabelList):
    parent_model = models.WorkflowJob
    resource_purpose = 'labels of a workflow job'


class JobActivityStreamList(SubListAPIView):
    model = models.ActivityStream
    serializer_class = serializers.ActivityStreamSerializer
    parent_model = models.Job
    relationship = 'activitystream_set'
    search_fields = ('changes',)
    resource_purpose = 'activity stream of a job'


class JobCancel(GenericCancelView):
    model = models.Job
    serializer_class = serializers.JobCancelSerializer
    resource_purpose = 'cancel for a job'

    @extend_schema_if_available(extensions={"x-ai-description": "Cancel a running job."})
    def post(self, request, *args, **kwargs):
        return super().post(request, *args, **kwargs)


class JobRelaunch(RetrieveAPIView):
    model = models.Job
    obj_permission_type = 'start'
    serializer_class = serializers.JobRelaunchSerializer
    resource_purpose = 'relaunch a job'

    def update_raw_data(self, data):
        data = super(JobRelaunch, self).update_raw_data(data)
        try:
            obj = self.get_object()
        except PermissionDenied:
            return data
        if obj:
            needed_passwords = obj.passwords_needed_to_start
            if needed_passwords:
                data['credential_passwords'] = {}
                for p in needed_passwords:
                    data['credential_passwords'][p] = u''
            else:
                data.pop('credential_passwords', None)
        return data

Review comment (suggestion):
```suggestion
    @extend_schema_if_available(extensions={"x-ai-description": "Cancel a running or pending job."})
```

Code after:
    def update(self, request, *args, **kwargs):
        obj = self.get_object()
        # Only allow changes (PUT/PATCH) when job status is "new".
        if obj.status != 'new':
            return self.http_method_not_allowed(request, *args, **kwargs)
        return super(JobDetail, self).update(request, *args, **kwargs)


class JobCredentialsList(SubListAPIView):
    model = models.Credential
    serializer_class = serializers.CredentialSerializer
    parent_model = models.Job
    relationship = 'credentials'
    resource_purpose = 'credentials of a job'


class JobLabelList(SubListAPIView):
    model = models.Label
    serializer_class = serializers.LabelSerializer
    parent_model = models.Job
    relationship = 'labels'
    resource_purpose = 'labels of a job'


class WorkflowJobLabelList(JobLabelList):
    parent_model = models.WorkflowJob
    resource_purpose = 'labels of a workflow job'


class JobActivityStreamList(SubListAPIView):
    model = models.ActivityStream
    serializer_class = serializers.ActivityStreamSerializer
    parent_model = models.Job
    relationship = 'activitystream_set'
    search_fields = ('changes',)
    resource_purpose = 'activity stream of a job'


class JobCancel(GenericCancelView):
    model = models.Job
    serializer_class = serializers.JobCancelSerializer
    resource_purpose = 'cancel for a job'

    @extend_schema_if_available(extensions={"x-ai-description": "Cancel a running or pending job"})
    def post(self, request, *args, **kwargs):
        return super().post(request, *args, **kwargs)


class JobRelaunch(RetrieveAPIView):
    model = models.Job
    obj_permission_type = 'start'