コード例 #1
0
    def create(self, validated_data, **kwargs):
        """Create the new object."""
        attributes = validated_data.get('attributes', {})
        if not isinstance(attributes, dict):
            raise APIException(
                _('Attributes must be a dictionary of (string, string) pairs.')
            )

        if any(not isinstance(key, str) or not isinstance(aval, str)
               for key, aval in list(attributes.items())):
            raise APIException(_('Attributes must be a dictionary (str, str)'))

        workflow_obj = None
        try:
            workflow_obj = Workflow(
                user=self.context['request'].user,
                name=validated_data['name'],
                description_text=validated_data.get('description_text', ''),
                nrows=0,
                ncols=0,
                attributes=attributes,
            )

            workflow_obj.save()
        except Exception:
            if workflow_obj and workflow_obj.id:
                workflow_obj.delete()
            raise APIException(_('Workflow could not be created.'))

        return workflow_obj
コード例 #2
0
ファイル: views.py プロジェクト: SmartJog/webengine-workflow
def create(request):
    options = request.POST

    if 'new_item' in options:
        items = Item.objects.order_by('-id')
        top_item_id = items and items[0].id or 0
        category_id = Category.objects.filter(id=options['category'])[0].id
        new_item = Item(id=top_item_id + 1, label=options['new_item'], details=options['details'], assigned_to_id=None, validation_id=3, category_id=category_id)
        new_item.save()
        return render_to_response('workflow/one_item.html', {'item' : new_item})

    if 'new_category' in options:
        categories = Category.objects.order_by('-id')
        top_category_id = categories and categories[0].id or 0
        orders = Category.objects.order_by('-order')
        top_order = orders and orders[0].id or 0
        new_category = Category(top_category_id + 1, options['new_category'], top_order, options['workflow_id'])
        new_category.save()
        return render_to_response('workflow/one_category.html', {'category' : new_category})

    if options['new_section']:
        sections = WorkflowSection.objects.order_by('-id')
        top_section_id = sections and sections[0].id or 0
        new_section = WorkflowSection(top_section_id + 1, options['new_section'])
        new_section.save()
    else:
        new_section = WorkflowSection.objects.filter(label=options['section'])[0]

    workflows = Workflow.objects.order_by('-id')
    top_id = workflows and workflows[0].id or 0
    new_workflow = Workflow(id=top_id + 1, workflow_section=new_section, label=options['new_workflow'])
    new_workflow.save()
    return HttpResponseRedirect(reverse('index'))
コード例 #3
0
def _do_clone_workflow(workflow: Workflow) -> Workflow:
    """Clone the workflow.

    :param workflow: source workflow

    :return: Clone object
    """
    new_workflow = Workflow(
        user=workflow.user,
        name=create_new_name(
            workflow.name,
            Workflow.objects.filter(
                Q(user=workflow.user) | Q(shared=workflow.user)),
        ),
        description_text=workflow.description_text,
        nrows=workflow.nrows,
        ncols=workflow.ncols,
        attributes=copy.deepcopy(workflow.attributes),
        query_builder_ops=copy.deepcopy(workflow.query_builder_ops),
        luser_email_column_md5=workflow.luser_email_column_md5,
        lusers_is_outdated=workflow.lusers_is_outdated)
    new_workflow.save()

    try:
        new_workflow.shared.set(list(workflow.shared.all()))
        new_workflow.lusers.set(list(workflow.lusers.all()))

        # Clone the columns
        for item_obj in workflow.columns.all():
            do_clone_column_only(item_obj, new_workflow=new_workflow)

        # Update the luser_email_column if needed:
        if workflow.luser_email_column:
            new_workflow.luser_email_column = new_workflow.columns.get(
                name=workflow.luser_email_column.name, )

        # Clone the DB table
        clone_table(workflow.get_data_frame_table_name(),
                    new_workflow.get_data_frame_table_name())

        # Clone actions
        for item_obj in workflow.actions.all():
            do_clone_action(item_obj, new_workflow)

        for item_obj in workflow.views.all():
            do_clone_view(item_obj, new_workflow)

        # Done!
        new_workflow.save()
    except Exception as exc:
        new_workflow.delete()
        raise exc

    return new_workflow
コード例 #4
0
ファイル: attribute.py プロジェクト: deborahlow97/ontask_b
def save_attribute_form(
    request: HttpRequest,
    workflow: Workflow,
    template: str,
    form: forms.Form,
    attr_idx: int
) -> JsonResponse:
    """Process the AJAX request to create or update an attribute.

    :param request: Request object received

    :param workflow: current workflow being manipulated

    :param template: Template to render in the response

    :param form: Form used to ask for data

    :param attr_idx: Index of the attribute being manipulated

    :return: AJAX reponse
    """
    if request.method == 'POST' and form.is_valid():
        # Correct form submitted
        if not form.has_changed():
            return JsonResponse({'html_redirect': None})

        # proceed with updating the attributes.
        wf_attributes = workflow.attributes

        # If key_idx is not -1, this means we are editing an existing pair
        if attr_idx != -1:
            key = sorted(wf_attributes.keys())[attr_idx]
            wf_attributes.pop(key)

            # Rename the appearances of the variable in all actions
            for action_item in workflow.actions.all():
                action_item.rename_variable(key, form.cleaned_data['key'])

        # Update value
        wf_attributes[form.cleaned_data['key']] = form.cleaned_data[
            'attr_value']

        workflow.attributes = wf_attributes
        workflow.save()

        # Log the event
        Log.objects.register(
            request.user,
            Log.WORKFLOW_ATTRIBUTE_CREATE,
            workflow,
            {
                'id': workflow.id,
                'name': workflow.name,
                'attr_key': form.cleaned_data['key'],
                'attr_val': form.cleaned_data['attr_value']})

        return JsonResponse({'html_redirect': ''})

    return JsonResponse({
        'html_form': render_to_string(
            template,
            {'form': form,
             'id': attr_idx},
            request=request),
    })
コード例 #5
0
    def create(self, validated_data, **kwargs):
        """Create the new workflow."""
        wflow_name = self.context.get('name')
        if not wflow_name:
            wflow_name = self.validated_data.get('name')
            if not wflow_name:
                raise Exception(_('Unexpected empty workflow name.'))

            if Workflow.objects.filter(name=wflow_name,
                                       user=self.context['user']).exists():
                raise Exception(
                    _('There is a workflow with this name. ' +
                      'Please provide a workflow name in the import page.'))

        # Initial values
        workflow_obj = None
        try:
            workflow_obj = Workflow(
                user=self.context['user'],
                name=wflow_name,
                description_text=validated_data['description_text'],
                nrows=0,
                ncols=0,
                attributes=validated_data['attributes'],
                query_builder_ops=validated_data.get('query_builder_ops', {}),
            )
            workflow_obj.save()

            # Create the columns
            column_data = ColumnSerializer(data=validated_data.get(
                'columns', []),
                                           many=True,
                                           context={'workflow': workflow_obj})
            # And save its content
            if column_data.is_valid():
                columns = column_data.save()
            else:
                raise Exception(_('Unable to save column information'))

            # If there is any column with position = 0, recompute (this is to
            # guarantee backward compatibility.
            if any(col.position == 0 for col in columns):
                for idx, col in enumerate(columns):
                    col.position = idx + 1
                    col.save()

            # Load the data frame
            data_frame = validated_data.get('data_frame')
            if data_frame is not None:
                # Store the table in the DB
                store_table(
                    data_frame,
                    workflow_obj.get_data_frame_table_name(),
                    dtype={
                        col.name: col.data_type
                        for col in workflow_obj.columns.all()
                    },
                )

                # Reconcile now the information in workflow and columns with
                # the one loaded
                workflow_obj.ncols = validated_data['ncols']
                workflow_obj.nrows = validated_data['nrows']

                workflow_obj.save()

            # Create the actions pointing to the workflow
            action_data = ActionSerializer(data=validated_data.get(
                'actions', []),
                                           many=True,
                                           context={
                                               'workflow': workflow_obj,
                                               'columns': columns
                                           })

            if action_data.is_valid():
                action_data.save()
            else:
                raise Exception(_('Unable to save column information'))

            # Create the views pointing to the workflow
            view_data = ViewSerializer(data=validated_data.get('views', []),
                                       many=True,
                                       context={
                                           'workflow': workflow_obj,
                                           'columns': columns
                                       })

            if view_data.is_valid():
                view_data.save()
            else:
                raise Exception(_('Unable to save column information'))
        except Exception:
            # Get rid of the objects created
            if workflow_obj:
                if workflow_obj.id:
                    workflow_obj.delete()
            raise

        return workflow_obj
コード例 #6
0
def workflow_delete_column(
    workflow: Workflow,
    column: Column,
    cond_to_delete: Optional[List[Condition]] = None,
):
    """Remove column from workflow.

    Given a workflow and a column, removes it from the workflow (and the
    corresponding data frame

    :param workflow: Workflow object

    :param column: Column object to delete

    :param cond_to_delete: List of conditions to delete after removing the
    column

    :return: Nothing. Effect reflected in the database
    """
    # Drop the column from the DB table storing the data frame
    df_drop_column(workflow.get_data_frame_table_name(), column.name)

    # Reposition the columns above the one being deleted
    workflow.reposition_columns(column.position, workflow.ncols + 1)

    # Delete the column
    column.delete()

    # Update the information in the workflow
    workflow.ncols = workflow.ncols - 1
    workflow.save()

    if not cond_to_delete:
        # The conditions to delete are not given, so calculate them
        # Get the conditions/actions attached to this workflow
        cond_to_delete = [
            cond
            for cond in Condition.objects.filter(action__workflow=workflow, )
            if column in cond.columns.all()
        ]

    # If a column disappears, the conditions that contain that variable
    # are removed
    actions_without_filters = []
    for condition in cond_to_delete:
        if condition.is_filter:
            actions_without_filters.append(condition.action)

        # Formula has the name of the deleted column. Delete it
        condition.delete()

    # Traverse the actions for which the filter has been deleted and reassess
    #  all their conditions
    # TODO: Explore how to do this asynchronously (or lazy)
    map(lambda act: act.update_n_rows_selected(), actions_without_filters)

    # If a column disappears, the views that contain only that column need to
    # disappear as well as they are no longer relevant.
    for view in workflow.views.all():
        if view.columns.count() == 0:
            view.delete()
コード例 #7
0
    def post(self, request, object_id=None, action=None):
        try:
            if not action:
                # return workflow_edit(request, None, api=True)
                pass

            enabled = request.POST.get('enabled') is not False
            defender_policy = False
            fqdn = ""
            public_dir = "/"

            try:
                frontend = Frontend.objects.get(pk=request.POST['frontend'])

                if frontend.mode == "http":
                    try:
                        fqdn = request.POST['fqdn']
                        if not validators.domain(fqdn):
                            return JsonResponse({
                                'error': _('This FQDN is not valid')
                            })

                        public_dir = request.POST['public_dir']
                        if public_dir and len(public_dir):
                            if public_dir[0] != '/':
                                public_dir = '/' + public_dir
                            if public_dir[-1] != '/':
                                public_dir += '/'

                    except KeyError:
                        return JsonResponse({
                            'error': _('For a HTTP Frontend, you must define a FQDN & a public_dir')
                        })
            except Frontend.DoesNotExist:
                return JsonResponse({
                    'error': _('frontend with id {} does not exist'.format(request.POST['frontend']))
                }, status=401)
            except KeyError:
                return JsonResponse({
                    'error': _('You must define a frontend for a workflow')
                }, status=401)

            try:
                backend = Backend.objects.get(pk=request.POST['backend'])

                if frontend.mode != backend.mode:
                    return JsonResponse({
                        'error': _('Frontend and Backend must be in the same mode.')
                    })
            except Backend.DoesNotExist:
                return JsonResponse({
                    'error': _('Backend with id {} does not exist'.format(request.POST['backend']))
                }, status=401)
            except KeyError:
                return JsonResponse({
                    'error': _('You must define a backend for a workflow')
                }, status=401)

            if request.POST.get('defender_policy'):
                try:
                    defender_policy = DefenderPolicy.objects.get(pk=request.POST['defender_policy'])
                except DefenderPolicy.DoesNotExist:
                    return JsonResponse({
                        'error': _('Defender Policy with id {} does not exist'.format(request.POST['defender_policy']))
                    }, status=401)

            try:
                if object_id:
                    workflow = Workflow.objects.get(pk=object_id)
                else:
                    workflow = Workflow()

                workflow.enabled = enabled
                workflow.name = request.POST['name']
                workflow.fqdn = fqdn
                workflow.public_dir = public_dir
                workflow.frontend = frontend
                workflow.backend = backend
                workflow.save()

                workflow_acls = []

                if defender_policy:
                    workflow.defender_policy = defender_policy

                workflow.workflowacl_set.all().delete()
                for i, tmp_acl in enumerate(json.loads(request.POST.get('acl_frontend', "[]"))):
                    status, acl = format_acl_from_api(tmp_acl, i, before_policy=True)
                    if not status:
                        return acl

                    acl.workflow = workflow
                    workflow_acls.append(acl)
                    acl.save()

                for i, tmp_acl in enumerate(json.loads(request.POST.get('acl_backend', "[]"))):
                    status, acl = format_acl_from_api(tmp_acl, i, before_policy=False)
                    if not status:
                        return acl

                    acl.workflow = workflow
                    workflow_acls.append(acl)
                    acl.save()

                workflow.workflow_json = generate_workflow(workflow)
                workflow.save()

                nodes = workflow.frontend.reload_conf()
                workflow.backend.reload_conf()

                if workflow.defender_policy:
                    logger.info("Need to reload the Defender Policy SPOE configuration")
                    Cluster.api_request(
                        "darwin.defender_policy.policy.write_defender_backend_conf",
                        workflow.defender_policy.pk
                    )
                    Cluster.api_request(
                        "darwin.defender_policy.policy.write_defender_spoe_conf",
                        workflow.defender_policy.pk
                    )

                # Reload HAProxy on concerned nodes
                for node in nodes:
                    api_res = node.api_request("services.haproxy.haproxy.restart_service")
                    if not api_res.get('status'):
                        logger.error("Workflow::edit: API error while trying to "
                                     "restart HAProxy service : {}".format(api_res.get('message')))
                        for workflow_acl in workflow.workflowacl_set.all():
                            workflow_acl.delete()

                        try:
                            workflow.delete()
                        except Exception:
                            pass

                        return JsonResponse({
                            'error': api_res.get('message')
                        }, status=500)

                return JsonResponse({
                    'message': _('Workflow saved')
                })

            except KeyError:
                return JsonResponse({
                    'error': _('Partial data')
                }, status=401)

            if action and not object_id:
                return JsonResponse({
                    'error': _('You must specify an ID')
                }, status=401)

            if action not in list(COMMAND_LIST.keys()):
                return JsonResponse({
                    'error': _('Action not allowed')
                }, status=403)

            return COMMAND_LIST[action](request, object_id, api=True)

        except Exception as e:
            logger.critical(e, exc_info=1)
            if settings.DEV_MODE:
                error = str(e)
            else:
                error = _("An error has occurred")

        return JsonResponse({
            'error': error
        }, status=500)