Example #1
0
def delete_rule(request, tid):
    rule = get_object_or_404(Rule, pk=tid)
    form = DeleteRuleForm(instance=rule)

    if request.method == 'POST':
        print >> sys.stderr, 'id' in request.POST
        print >> sys.stderr, str(rule.id) == request.POST['id']
        print >> sys.stderr, str(rule.id) == request.POST['id']
        # if 'id' in request.POST and str(rule.id) == request.POST['id']:
        form = DeleteRuleForm(request.POST, instance=rule)
        print >> sys.stderr, form.is_valid()
        print >> sys.stderr, form.errors
        print >> sys.stderr, form.non_field_errors()
        print >> sys.stderr, 'id' in request.POST
        if form.is_valid():
            rule.delete()
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Rule deleted.',
                                 extra_tags='alert-success')
            return HttpResponseRedirect(reverse('rules'))

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([rule])
    rels = collector.nested()

    add_breadcrumb(parent=rule, title="Delete", top_level=False, request=request)
    system_settings = System_Settings.objects.get()
    return render(request, 'dojo/delete_rule.html',
                  {'rule': rule,
                   'form': form,
                   'active_tab': 'findings',
                   'system_settings': system_settings,
                   'rels': rels,
                   })
Example #2
0
    def _update_related_nested(self, account_type, from_instances, to_instance, to_merge):
        ignored = []
        updated = collections.defaultdict(int)

        collector = NestedObjects(using=DEFAULT_DB_ALIAS)
        collector.collect(from_instances)

        # FIXME: could handle multiple sets but will be good to test format returned by nested()
        try:
            (from_instance, related_instances) = collector.nested()
        except ValueError:
            raise CommandError("related item look-up error")

        ignored.append(from_instance)
        for related_instance in related_instances:
            if isinstance(related_instance, list):
                # NOTE: This should be a collection of related-related-objects,
                # NOTE: and as such only a concern if their link is deleted
                #
                # FIXME: worth bothering?
                pass
            elif related_instance._meta.model in to_merge:
                setattr(related_instance, account_type, to_instance)
                related_instance.save(update_fields=(account_type,))
                updated[related_instance._meta.model] += 1
            else:
                ignored.append(related_instance)

        return updated, ignored
Example #3
0
class NestedObjectsTests(TestCase):
    """
    Tests for ``NestedObject`` utility collection.
    """
    def setUp(self):
        self.n = NestedObjects(using=DEFAULT_DB_ALIAS)
        self.objs = [Count.objects.create(num=i) for i in range(5)]

    def _check(self, target):
        self.assertEqual(self.n.nested(lambda obj: obj.num), target)

    def _connect(self, i, j):
        self.objs[i].parent = self.objs[j]
        self.objs[i].save()

    def _collect(self, *indices):
        self.n.collect([self.objs[i] for i in indices])

    def test_unrelated_roots(self):
        self._connect(2, 1)
        self._collect(0)
        self._collect(1)
        self._check([0, 1, [2]])

    def test_siblings(self):
        self._connect(1, 0)
        self._connect(2, 0)
        self._collect(0)
        self._check([0, [1, 2]])

    def test_non_added_parent(self):
        self._connect(0, 1)
        self._collect(0)
        self._check([0])

    def test_cyclic(self):
        self._connect(0, 2)
        self._connect(1, 0)
        self._connect(2, 1)
        self._collect(0)
        self._check([0, [1, [2]]])

    def test_queries(self):
        self._connect(1, 0)
        self._connect(2, 0)
        # 1 query to fetch all children of 0 (1 and 2)
        # 1 query to fetch all children of 1 and 2 (none)
        # Should not require additional queries to populate the nested graph.
        self.assertNumQueries(2, self._collect, 0)

    def test_on_delete_do_nothing(self):
        """
        Check that the nested collector doesn't query for DO_NOTHING objects.
        """
        n = NestedObjects(using=DEFAULT_DB_ALIAS)
        objs = [Event.objects.create()]
        EventGuide.objects.create(event=objs[0])
        with self.assertNumQueries(2):
            # One for Location, one for Guest, and no query for EventGuide
            n.collect(objs)
Example #4
0
def delete_jira(request, tid):
    inst = get_object_or_404(JIRA_Conf, pk=tid)
    #eng = test.engagement
    #TODO Make Form
    form = DeleteJIRAConfForm(instance=inst)

    from django.contrib.admin.utils import NestedObjects
    from django.db import DEFAULT_DB_ALIAS

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([inst])
    rels = collector.nested()

    if request.method == 'POST':
        if 'id' in request.POST and str(inst.id) == request.POST['id']:
            form = DeleteJIRAConfForm(request.POST, instance=inst)
            if form.is_valid():
                inst.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'JIRA Conf and relationships removed.',
                                     extra_tags='alert-success')
                return HttpResponseRedirect(reverse('jira'))

    add_breadcrumb(title="Delete", top_level=False, request=request)
    return render(request, 'dojo/delete_jira.html', {
        'inst': inst,
        'form': form,
        'rels': rels,
        'deletable_objects': rels,
    })
Example #5
0
    def get_deleted_objects(self, objs, request):
        # we override here to allow soft_delete, modified from
        # https://github.com/django/django/blob/master/django/contrib/admin/utils.py
        """
        Find all objects related to ``objs`` that should also be deleted. ``objs``
        must be a homogeneous iterable of objects (e.g. a QuerySet).
        Return a nested list of strings suitable for display in the
        template with the ``unordered_list`` filter.
        """
        try:
            obj = objs[0]
        except IndexError:
            return [], {}, set(), []
        else:
            using = router.db_for_write(obj._meta.model)
        collector = NestedObjects(using=using)
        collector.collect(objs)

        def format_callback(obj):
            return '%s: %s' % (capfirst(obj._meta.verbose_name), obj)

        to_delete = collector.nested(format_callback)
        model_count = {model._meta.verbose_name_plural: len(objs) for model, objs in collector.model_objs.items()}
        # we need to display count by model of the protected items too
        protected = [format_callback(obj) for obj in collector.protected]
        protected_model = {obj._meta.verbose_name_plural for obj in collector.protected}
        protected_model_count = dict(Counter(protected_model))
        # since we are only performing soft delete, we may soft delete the protected objects later
        return to_delete + protected, {**model_count, **protected_model_count}, set(), []
Example #6
0
class NestedObjectsTests(TestCase):
    """
    Tests for ``NestedObject`` utility collection.
    """
    def setUp(self):
        self.n = NestedObjects(using=DEFAULT_DB_ALIAS)
        self.objs = [Count.objects.create(num=i) for i in range(5)]

    def _check(self, target):
        self.assertEqual(self.n.nested(lambda obj: obj.num), target)

    def _connect(self, i, j):
        self.objs[i].parent = self.objs[j]
        self.objs[i].save()

    def _collect(self, *indices):
        self.n.collect([self.objs[i] for i in indices])

    def test_unrelated_roots(self):
        self._connect(2, 1)
        self._collect(0)
        self._collect(1)
        self._check([0, 1, [2]])

    def test_siblings(self):
        self._connect(1, 0)
        self._connect(2, 0)
        self._collect(0)
        self._check([0, [1, 2]])

    def test_non_added_parent(self):
        self._connect(0, 1)
        self._collect(0)
        self._check([0])

    def test_cyclic(self):
        self._connect(0, 2)
        self._connect(1, 0)
        self._connect(2, 1)
        self._collect(0)
        self._check([0, [1, [2]]])

    def test_queries(self):
        self._connect(1, 0)
        self._connect(2, 0)
        # 1 query to fetch all children of 0 (1 and 2)
        # 1 query to fetch all children of 1 and 2 (none)
        # Should not require additional queries to populate the nested graph.
        self.assertNumQueries(2, self._collect, 0)

    def test_on_delete_do_nothing(self):
        """
        Check that the nested collector doesn't query for DO_NOTHING objects.
        """
        n = NestedObjects(using=DEFAULT_DB_ALIAS)
        objs = [Event.objects.create()]
        EventGuide.objects.create(event=objs[0])
        with self.assertNumQueries(2):
            # One for Location, one for Guest, and no query for EventGuide
            n.collect(objs)
Example #7
0
 def get_nested_objects(cls, obj):
     using = router.db_for_write(cls.model)
     collector = NestedObjects(using=using)
     collector.collect([obj])
     nested = collector.nested(cls._format_obj)
     collector.dependencies
     return nested, list(map(cls._format_obj, collector.protected))
Example #8
0
def delete_test(request, tid):
    test = get_object_or_404(Test, pk=tid)
    eng = test.engagement
    form = DeleteTestForm(instance=test)

    from django.contrib.admin.utils import NestedObjects
    from django.db import DEFAULT_DB_ALIAS

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([test])
    rels = collector.nested()

    if request.method == 'POST':
        if 'id' in request.POST and str(test.id) == request.POST['id']:
            form = DeleteTestForm(request.POST, instance=test)
            if form.is_valid():
                del test.tags
                test.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'Test and relationships removed.',
                                     extra_tags='alert-success')
                return HttpResponseRedirect(reverse('view_engagement', args=(eng.id,)))

    add_breadcrumb(parent=test, title="Delete", top_level=False, request=request)
    return render(request, 'dojo/delete_test.html',
                  {'test': test,
                   'form': form,
                   'rels': rels,
                   'deletable_objects': rels,
                   })
Example #9
0
    def process_preview(self, request, form, context):

        if "_delete" in request.POST:

            def format_callback(obj):
                return '%s: %s' % (capfirst(obj._meta.verbose_name), obj)

            ps = form.cleaned_data['teams']
            collector = NestedObjects(using='default')  # or specific database
            collector.collect(ps)
            to_delete = collector.nested(format_callback)

            context['objs'] = to_delete

        elif "_competing" in request.POST:

            self.preview_template = "plan/teamCompetePreview.html"

            teams = []
            nt = form.cleaned_data['teams']

            for t in nt:

                teams.append({
                    "name": t.origin.name,
                    "competing": not t.is_competing
                })

            context['teams'] = teams
            context['action'] = "_competing"
Example #10
0
def delete_engagement(request, eid):
    engagement = get_object_or_404(Engagement, pk=eid)
    product = engagement.product
    form = DeleteEngagementForm(instance=engagement)

    if request.method == 'POST':
        if 'id' in request.POST and str(engagement.id) == request.POST['id']:
            form = DeleteEngagementForm(request.POST, instance=engagement)
            if form.is_valid():
                del engagement.tags
                engagement.delete()
                messages.add_message(
                    request,
                    messages.SUCCESS,
                    'Engagement and relationships removed.',
                    extra_tags='alert-success')
                return HttpResponseRedirect(reverse("view_engagements", args=(product.id, )))

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([engagement])
    rels = collector.nested()

    product_tab = Product_Tab(product.id, title="Delete Engagement", tab="engagements")
    product_tab.setEngagement(engagement)
    return render(request, 'dojo/delete_engagement.html', {
        'product_tab': product_tab,
        'engagement': engagement,
        'form': form,
        'rels': rels,
    })
Example #11
0
def delete_survey(request, sid):
    survey = get_object_or_404(Engagement_Survey, id=sid)
    form = Delete_Eng_Survey_Form(instance=survey)

    from django.contrib.admin.utils import NestedObjects
    from django.db import DEFAULT_DB_ALIAS

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([survey])
    rels = collector.nested()

    if request.method == 'POST':
        if 'id' in request.POST and str(survey.id) == request.POST['id']:
            form = Delete_Eng_Survey_Form(request.POST, instance=survey)
            if form.is_valid():
                survey.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'Questionnaire and relationships removed.',
                                     extra_tags='alert-success')
                return HttpResponseRedirect(reverse('survey'))
    add_breadcrumb(title="Delete", top_level=False, request=request)
    return render(request, 'defectDojo-engagement-survey/delete_survey.html',
                  {'survey': survey,
                   'form': form,
                   'rels': rels,
                   })
Example #12
0
def delete_endpoint(request, eid):
    endpoint = get_object_or_404(Endpoint, pk=eid)
    product = endpoint.product
    form = DeleteEndpointForm(instance=endpoint)

    if request.method == 'POST':
        if 'id' in request.POST and str(endpoint.id) == request.POST['id']:
            form = DeleteEndpointForm(request.POST, instance=endpoint)
            if form.is_valid():
                del endpoint.tags
                endpoint.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'Endpoint and relationships removed.',
                                     extra_tags='alert-success')
                return HttpResponseRedirect(
                    reverse('view_endpoint', args=(product.id, )))

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([endpoint])
    rels = collector.nested()

    product_tab = Product_Tab(endpoint.product.id,
                              "Delete Endpoint",
                              tab="endpoints")

    return render(
        request, 'dojo/delete_endpoint.html', {
            'endpoint': endpoint,
            'product_tab': product_tab,
            'form': form,
            'rels': rels,
        })
Example #13
0
def merge_users(user, user_uuid):
    existing_user, created = get_user_model().objects.get_or_create(
        uuid=user_uuid, defaults={'is_active': True})

    collector = NestedObjects(using='default')
    collector.collect([user])
    to_change_user = collector.nested()
    try:
        related_objects = to_change_user[1]
    except IndexError:
        related_objects = []
    for related_object in related_objects:
        if getattr(related_object, 'user', None) == user:
            related_object.user = existing_user
            related_object.save()
        if getattr(related_object, 'created_by', None) == user:
            related_object.created_by = existing_user
            related_object.save()

    for group in user.communication_groups.all():
        group.users.add(existing_user)
    if hasattr(existing_user, 'participant'):
        participant = existing_user.participant
        participant.delete()
    user.delete()
Example #14
0
def delete_user(request, uid):
    user = get_object_or_404(Dojo_User, id=uid)
    form = DeleteUserForm(instance=user)

    from django.contrib.admin.utils import NestedObjects
    from django.db import DEFAULT_DB_ALIAS

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([user])
    rels = collector.nested()

    if user.id == request.user.id:
        messages.add_message(request,
                             messages.ERROR,
                             'You may not delete yourself.',
                             extra_tags='alert-danger')
        return HttpResponseRedirect(reverse('edit_user', args=(user.id,)))

    if request.method == 'POST':
        if 'id' in request.POST and str(user.id) == request.POST['id']:
            form = DeleteUserForm(request.POST, instance=user)
            if form.is_valid():
                user.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'User and relationships removed.',
                                     extra_tags='alert-success')
                return HttpResponseRedirect(reverse('users'))
    add_breadcrumb(title="Delete User", top_level=False, request=request)
    return render(request, 'dojo/delete_user.html',
                  {'to_delete': user,
                   'form': form,
                   'rels': rels,
                   })
Example #15
0
class DeleteViewWithDependencies(FlagMixin, RulesRequiredMixin, AjaxTemplateMixin, DeleteView):
    success_message = "The objects are been deleted successfully"
    protected_template = None

    collector = None

    def get(self, request, *args, **kwargs):
        self.collector = NestedObjects(using="default")

        self.get_collect()
        self.post_collect()

        # If there is some protected objects, change the template
        if self.collector.protected:
            self.template_name = self.protected_template

        return super().get(request, *args, **kwargs)

    def get_collect(self):
        # Collect objects how will be deleted
        self.collector.collect([self.get_object()])

    def post_collect(self):
        pass

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["deletable_objects"] = self.collector.nested(format_callback)
        context["protected_objects"] = self.collector.protected
        return context

    def delete(self, request, *args, **kwargs):
        result = super().delete(request, *args, **kwargs)
        display_success_messages(request, _(self.success_message))
        return result
Example #16
0
def delete_github(request, tid):
    github_instance = get_object_or_404(GITHUB_Conf, pk=tid)
    # eng = test.engagement
    # TODO Make Form
    form = DeleteGITHUBConfForm(instance=github_instance)

    if request.method == 'POST':
        if 'id' in request.POST and str(
                github_instance.id) == request.POST['id']:
            form = DeleteGITHUBConfForm(request.POST, instance=github_instance)
            if form.is_valid():
                github_instance.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'Github Conf and relationships removed.',
                                     extra_tags='alert-success')
                return HttpResponseRedirect(reverse('github'))

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([github_instance])
    rels = collector.nested()

    add_breadcrumb(title="Delete", top_level=False, request=request)
    return render(
        request, 'dojo/delete_github.html', {
            'inst': github_instance,
            'form': form,
            'rels': rels,
            'deletable_objects': rels,
        })
Example #17
0
def delete_user(request, uid):
    user = get_object_or_404(Dojo_User, id=uid)
    form = DeleteUserForm(instance=user)

    if user.id == request.user.id:
        messages.add_message(request,
                             messages.ERROR,
                             'You may not delete yourself.',
                             extra_tags='alert-danger')
        return HttpResponseRedirect(reverse('edit_user', args=(user.id,)))

    if request.method == 'POST':
        if 'id' in request.POST and str(user.id) == request.POST['id']:
            form = DeleteUserForm(request.POST, instance=user)
            if form.is_valid():
                user.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'User and relationships removed.',
                                     extra_tags='alert-success')
                return HttpResponseRedirect(reverse('users'))

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([user])
    rels = collector.nested()

    add_breadcrumb(title="Delete User", top_level=False, request=request)
    return render(request, 'dojo/delete_user.html',
                  {'to_delete': user,
                   'form': form,
                   'rels': rels,
                   })
Example #18
0
def delete_product(request, pid):
    product = get_object_or_404(Product, pk=pid)
    form = DeleteProductForm(instance=product)

    if request.method == 'POST':
        if 'id' in request.POST and str(product.id) == request.POST['id']:
            form = DeleteProductForm(request.POST, instance=product)
            if form.is_valid():
                if product.tags:
                    del product.tags
                product.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'Product and relationships removed.',
                                     extra_tags='alert-success')
                return HttpResponseRedirect(reverse('product'))

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([product])
    rels = collector.nested()

    product_tab = Product_Tab(pid, title="Product", tab="settings")
    return render(request, 'dojo/delete_product.html',
                  {'product': product,
                   'form': form,
                   'product_tab': product_tab,
                   'rels': rels,
                   })
    def _related_objects(self, using):
        """
        Method to get all objects with foreign key the relation with self instance
        Args:
            self
        Returns:
            List(): all related objects
        """
        using = using or router.db_for_write(self.__class__, instance=self)

        collector = NestedObjects(using=using)
        collector.collect([self])

        def parse_list(obj):
            """
            Parse to nested objects
            Args:
                obj: list instance or models object instance
            Returns:
                list(): list with objects
            """
            if isinstance(obj, list):
                array = []
                for item in obj:
                    array += parse_list(item)
                return array
            return [obj]

        colletion = parse_list(collector.nested())
        colletion.remove(self)

        return colletion
Example #20
0
def get_deleted_objects(objs, request):
    try:
        obj = objs[0]
    except IndexError:
        return [], {}, set(), []
    else:
        using = router.db_for_write(obj._meta.model)
    collector = NestedObjects(using=using)
    collector.collect(objs)
    perms_needed = set()

    def format_callback(obj):
        opts = obj._meta
        no_edit_link = '%s: %s' % (capfirst(opts.verbose_name), obj)
        perms_needed.add(opts.verbose_name)

        try:
            return format_html('{}: <a href="{}">{}</a>',
                               capfirst(opts.verbose_name),
                               obj.get_absolute_url(), obj)
        except AttributeError:
            return no_edit_link

    to_delete = collector.nested(format_callback)

    protected = [format_callback(obj) for obj in collector.protected]
    model_count = {
        model._meta.verbose_name_plural: len(objs)
        for model, objs in collector.model_objs.items()
    }

    return to_delete, model_count, perms_needed, protected
Example #21
0
def delete_endpoint(request, eid):
    endpoint = get_object_or_404(Endpoint, pk=eid)
    product = endpoint.product
    form = DeleteEndpointForm(instance=endpoint)

    if request.method == 'POST':
        if 'id' in request.POST and str(endpoint.id) == request.POST['id']:
            form = DeleteEndpointForm(request.POST, instance=endpoint)
            if form.is_valid():
                product = endpoint.product
                endpoint.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'Endpoint and relationships removed.',
                                     extra_tags='alert-success')
                create_notification(event='other',
                                    title='Deletion of %s' % endpoint,
                                    product=product,
                                    description='The endpoint "%s" was deleted by %s' % (endpoint, request.user),
                                    url=request.build_absolute_uri(reverse('endpoint')),
                                    icon="exclamation-triangle")
                return HttpResponseRedirect(reverse('view_product', args=(product.id,)))

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([endpoint])
    rels = collector.nested()

    product_tab = Product_Tab(endpoint.product.id, "Delete Endpoint", tab="endpoints")

    return render(request, 'dojo/delete_endpoint.html',
                  {'endpoint': endpoint,
                   'product_tab': product_tab,
                   'form': form,
                   'rels': rels,
                   })
Example #22
0
def delete_jira(request, tid):
    jira_instance = get_object_or_404(JIRA_Conf, pk=tid)
    # eng = test.engagement
    # TODO Make Form
    form = DeleteJIRAConfForm(instance=jira_instance)

    if request.method == 'POST':
        if 'id' in request.POST and str(jira_instance.id) == request.POST['id']:
            form = DeleteJIRAConfForm(request.POST, instance=jira_instance)
            if form.is_valid():
                jira_instance.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'JIRA Conf and relationships removed.',
                                     extra_tags='alert-success')
                create_notification(event='other',
                                    title='Deletion of JIRA URL %s' % jira_instance.url,
                                    description='JIRA url "%s" was deleted by %s' % (jira_instance.url, request.user),
                                    url=request.build_absolute_uri(reverse('jira')),
                                    )
                return HttpResponseRedirect(reverse('jira'))

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([jira_instance])
    rels = collector.nested()

    add_breadcrumb(title="Delete", top_level=False, request=request)
    return render(request, 'dojo/delete_jira.html',
                  {'inst': jira_instance,
                   'form': form,
                   'rels': rels,
                   'deletable_objects': rels,
                   })
Example #23
0
def delete_engagement_presets(request, pid, eid):
    prod = get_object_or_404(Product, id=pid)
    preset = get_object_or_404(Engagement_Presets, id=eid)
    form = DeleteEngagementPresetsForm(instance=preset)

    from django.contrib.admin.utils import NestedObjects
    from django.db import DEFAULT_DB_ALIAS

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([preset])
    rels = collector.nested()

    if request.method == 'POST':
        if 'id' in request.POST:
            form = DeleteEngagementPresetsForm(request.POST, instance=preset)
            if form.is_valid():
                preset.delete()
                messages.add_message(
                    request,
                    messages.SUCCESS,
                    'Engagement presets and engagement relationships removed.',
                    extra_tags='alert-success')
                return HttpResponseRedirect(
                    reverse('engagement_presets', args=(pid, )))

    product_tab = Product_Tab(pid,
                              title="Delete Engagement Preset",
                              tab="settings")
    return render(
        request, 'dojo/delete_presets.html', {
            'product': product,
            'form': form,
            'product_tab': product_tab,
            'rels': rels,
        })
Example #24
0
    def get_deleted_objects(objs):
        """Based on `django/contrib/admin/utils.py`"""
        collector = NestedObjects(using="default")
        collector.collect(objs)

        def format_callback(obj):
            opts = obj._meta
            # Display a link to the admin page.
            try:
                return format_html(
                    '{}: <a href="{}">{}</a>',
                    capfirst(opts.verbose_name),
                    reverse(app_urlname(opts, "update"), kwargs={"pk":
                                                                 obj.pk}),
                    obj,
                )
            except NoReverseMatch:
                pass

            no_edit_link = "%s: %s" % (capfirst(
                opts.verbose_name), force_text(obj))
            return no_edit_link

        to_delete = collector.nested(format_callback)
        protected = [format_callback(obj) for obj in collector.protected]
        model_count = {
            model._meta.verbose_name_plural: len(objs)
            for model, objs in collector.model_objs.items()
        }

        return to_delete, model_count, protected
Example #25
0
def delete_product(request, pid):
    product = get_object_or_404(Product, pk=pid)
    form = DeleteProductForm(instance=product)

    from django.contrib.admin.utils import NestedObjects
    from django.db import DEFAULT_DB_ALIAS

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([product])
    rels = collector.nested()

    if request.method == 'POST':
        if 'id' in request.POST and str(product.id) == request.POST['id']:
            form = DeleteProductForm(request.POST, instance=product)
            if form.is_valid():
                if product.tags:
                    del product.tags
                product.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'Product and relationships removed.',
                                     extra_tags='alert-success')
                return HttpResponseRedirect(reverse('product'))

    add_breadcrumb(parent=product, title="Delete", top_level=False, request=request)

    return render(request, 'dojo/delete_product.html',
                  {'product': product,
                   'form': form,
                   'rels': rels,
                   })
Example #26
0
def delete_group(request, gid):
    group = get_object_or_404(Dojo_Group, id=gid)
    form = DeleteGroupForm(instance=group)

    if request.method == 'POST':
        if 'id' in request.POST and str(group.id) == request.POST['id']:
            form = DeleteGroupForm(request.POST, instance=group)
            if form.is_valid():
                try:
                    group.delete()
                    messages.add_message(
                        request,
                        messages.SUCCESS,
                        'Group and relationships successfully removed.',
                        extra_tags='alert-success')
                except RestrictedError as err:
                    messages.add_message(
                        request,
                        messages.WARNING,
                        'Group cannot be deleted: {}'.format(err),
                        extra_tags='alert-warning')
                return HttpResponseRedirect(reverse('groups'))

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([group])
    rels = collector.nested()
    add_breadcrumb(title="Delete Group", top_level=False, request=request)
    return render(request, 'dojo/delete_group.html', {
        'to_delete': group,
        'form': form,
        'rels': rels
    })
Example #27
0
def delete_jira(request, tid):
    jira_instance = get_object_or_404(JIRA_Conf, pk=tid)
    # eng = test.engagement
    # TODO Make Form
    form = DeleteJIRAConfForm(instance=jira_instance)

    if request.method == 'POST':
        if 'id' in request.POST and str(jira_instance.id) == request.POST['id']:
            form = DeleteJIRAConfForm(request.POST, instance=jira_instance)
            if form.is_valid():
                jira_instance.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'JIRA Conf and relationships removed.',
                                     extra_tags='alert-success')
                return HttpResponseRedirect(reverse('jira'))

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([jira_instance])
    rels = collector.nested()

    add_breadcrumb(title="Delete", top_level=False, request=request)
    return render(request, 'dojo/delete_jira.html',
                  {'inst': jira_instance,
                   'form': form,
                   'rels': rels,
                   'deletable_objects': rels,
                   })
Example #28
0
def delete_product(request, pid):
    product = get_object_or_404(Product, pk=pid)
    form = DeleteProductForm(instance=product)

    from django.contrib.admin.utils import NestedObjects
    from django.db import DEFAULT_DB_ALIAS

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([product])
    rels = collector.nested()

    if request.method == 'POST':
        if 'id' in request.POST and str(product.id) == request.POST['id']:
            form = DeleteProductForm(request.POST, instance=product)
            if form.is_valid():
                if product.tags:
                    del product.tags
                product.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'Product and relationships removed.',
                                     extra_tags='alert-success')
                return HttpResponseRedirect(reverse('product'))

    product_tab = Product_Tab(pid, title="Product", tab="settings")
    return render(
        request, 'dojo/delete_product.html', {
            'product': product,
            'form': form,
            'product_tab': product_tab,
            'rels': rels,
        })
Example #29
0
 def get_context_data(self, **kwargs):
     context = super(Delete, self).get_context_data(**kwargs)
     context['list_reversed_url'] = reverse_lazy(ADDRESS_LIST_URL_NAME)
     collector = NestedObjects(using='default')
     collector.collect([self.get_object()])
     context['deleted_objects'] = collector.nested()
     return context
Example #30
0
def delete_engagement(request, eid):
    engagement = get_object_or_404(Engagement, pk=eid)
    product = engagement.product
    form = DeleteEngagementForm(instance=engagement)

    from django.contrib.admin.utils import NestedObjects
    from django.db import DEFAULT_DB_ALIAS

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([engagement])
    rels = collector.nested()

    if request.method == 'POST':
        if 'id' in request.POST and str(engagement.id) == request.POST['id']:
            form = DeleteEngagementForm(request.POST, instance=engagement)
            if form.is_valid():
                del engagement.tags
                engagement.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'Engagement and relationships removed.',
                                     extra_tags='alert-success')
                return HttpResponseRedirect(
                    reverse('view_product', args=(product.id, )))

    add_breadcrumb(parent=engagement,
                   title="Delete",
                   top_level=False,
                   request=request)

    return render(request, 'dojo/delete_engagement.html', {
        'engagement': engagement,
        'form': form,
        'rels': rels,
    })
Example #31
0
def delete_engagement_presets(request, pid, eid):
    prod = get_object_or_404(Product, id=pid)
    preset = get_object_or_404(Engagement_Presets, id=eid)
    form = DeleteEngagementPresetsForm(instance=preset)

    if request.method == 'POST':
        if 'id' in request.POST:
            form = DeleteEngagementPresetsForm(request.POST, instance=preset)
            if form.is_valid():
                preset.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'Engagement presets and engagement relationships removed.',
                                     extra_tags='alert-success')
                return HttpResponseRedirect(reverse('engagement_presets', args=(pid,)))

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([preset])
    rels = collector.nested()

    product_tab = Product_Tab(pid, title="Delete Engagement Preset", tab="settings")
    return render(request, 'dojo/delete_presets.html',
                  {'product': product,
                   'form': form,
                   'product_tab': product_tab,
                   'rels': rels,
                   })
Example #32
0
def delete_test(request, tid):
    test = get_object_or_404(Test, pk=tid)
    eng = test.engagement
    form = DeleteTestForm(instance=test)

    if request.method == 'POST':
        if 'id' in request.POST and str(test.id) == request.POST['id']:
            form = DeleteTestForm(request.POST, instance=test)
            if form.is_valid():
                del test.tags
                test.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'Test and relationships removed.',
                                     extra_tags='alert-success')
                return HttpResponseRedirect(reverse('view_engagement', args=(eng.id,)))

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([test])
    rels = collector.nested()

    product_tab = Product_Tab(test.engagement.product.id, title="Delete Test", tab="engagements")
    product_tab.setEngagement(test.engagement)
    return render(request, 'dojo/delete_test.html',
                  {'test': test,
                   'product_tab': product_tab,
                   'form': form,
                   'rels': rels,
                   'deletable_objects': rels,
                   })
Example #33
0
def delete_test(request, tid):
    test = get_object_or_404(Test, pk=tid)
    eng = test.engagement
    form = DeleteTestForm(instance=test)

    if request.method == 'POST':
        if 'id' in request.POST and str(test.id) == request.POST['id']:
            form = DeleteTestForm(request.POST, instance=test)
            if form.is_valid():
                del test.tags
                test.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'Test and relationships removed.',
                                     extra_tags='alert-success')
                return HttpResponseRedirect(reverse('view_engagement', args=(eng.id,)))

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([test])
    rels = collector.nested()

    product_tab = Product_Tab(test.engagement.product.id, title="Delete Test", tab="engagements")
    product_tab.setEngagement(test.engagement)
    return render(request, 'dojo/delete_test.html',
                  {'test': test,
                   'product_tab': product_tab,
                   'form': form,
                   'rels': rels,
                   'deletable_objects': rels,
                   })
Example #34
0
def delete_product_type(request, ptid):
    product_type = get_object_or_404(Product_Type, pk=ptid)
    form = Delete_Product_TypeForm(instance=product_type)

    if request.method == 'POST':
        if 'id' in request.POST and str(product_type.id) == request.POST['id']:
            form = Delete_Product_TypeForm(request.POST, instance=product_type)
            if form.is_valid():
                product_type.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'Product Type and relationships removed.',
                                     extra_tags='alert-success')
                create_notification(
                    event='other',
                    title='Deletion of %s' % product_type.name,
                    description='The product type "%s" was deleted by %s' %
                    (product_type.name, request.user),
                    url=request.build_absolute_uri(reverse('product_type')),
                    icon="exclamation-triangle")
                return HttpResponseRedirect(reverse('product_type'))

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([product_type])
    rels = collector.nested()

    add_breadcrumb(title="Delete Product Type",
                   top_level=False,
                   request=request)
    return render(request, 'dojo/delete_product_type.html', {
        'product_type': product_type,
        'form': form,
        'rels': rels,
    })
Example #35
0
def delete_product(request, pid):
    product = get_object_or_404(Product, pk=pid)
    form = DeleteProductForm(instance=product)

    if request.method == 'POST':
        if 'id' in request.POST and str(product.id) == request.POST['id']:
            form = DeleteProductForm(request.POST, instance=product)
            if form.is_valid():
                if product.tags:
                    del product.tags
                product.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'Product and relationships removed.',
                                     extra_tags='alert-success')
                create_notification(event='other',
                                    title='Deletion of %s' % product.name,
                                    description='The product "%s" was deleted by %s' % (product.name, request.user),
                                    url=request.build_absolute_uri(reverse('product')),
                                    icon="exclamation-triangle")
                return HttpResponseRedirect(reverse('product'))

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([product])
    rels = collector.nested()

    product_tab = Product_Tab(pid, title="Product", tab="settings")
    return render(request, 'dojo/delete_product.html',
                  {'product': product,
                   'form': form,
                   'product_tab': product_tab,
                   'rels': rels,
                   })
Example #36
0
    def xls_export(self, _models, root=None, root_qs=None):
        if (root and root_qs) or ((root or root_qs) is None):
            raise RuntimeError(
                _("Either a root object or a root queryset must be provided"))

        workbook = None
        try:
            workbookfile = self.dest or NamedTemporaryFile(dir=self.tmpdir,
                                                           delete=False)
            workbook = Workbook()
            del workbook['Sheet']

            sheets = {}

            lmodels = {}
            for k, v in _models.items():
                lname = k.lower()
                model_name = lname.rsplit('.')[1]
                lmodels[lname] = v
                sheets[model_name] = workbook.create_sheet(title=model_name)
                sheets[model_name].append(v)

            if root:
                root_qs = root._meta.model.objects.filter(pk=root.pk)

            using = router.db_for_write(root_qs.first()._meta.model)
            collector = NestedObjects(using=using)
            collector.collect(root_qs)

            def callback(obj):
                fields = lmodels.get(obj._meta.label_lower, None)
                if fields:
                    sheets[obj._meta.model_name].append(
                        [getattr(obj, x) for x in fields])

            collector.nested(callback)
            workbook.save(workbookfile)
            return workbookfile.name

        except Exception as e:
            if workbook:
                if not workbookfile.closed:
                    workbookfile.close()
                if os.path.exists(workbookfile.name):
                    os.remove(workbookfile.name)
            raise e
Example #37
0
def get_deleted_objects(object):
    """
    List the related objects before delete an object
    """
    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([object])

    return collector.nested()
def model_has_related_objects(model):
    collector = NestedObjects(using="default")
    collector.collect([model])
    collected = collector.nested()
    if len(collected) >= 2:
        return collected[1]
    assert collected[0] == model
    return False
def cascade_activate(obj, using=None):
    if using is None:
        using = DEFAULT_DB_ALIAS

    collector = NestedObjects(using)
    collector.collect([obj])

    activate(collector.nested())
Example #40
0
def get_deleted_objects(object):
    """
    List the related objects before delete an object
    """
    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([object])

    return collector.nested()
Example #41
0
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        collector = NestedObjects(using='default')
        collector.collect([self.get_object()])
        context['deleted_objects'] = collector.nested()

        return context
Example #42
0
    def get_deleted_objects(self):
        collector = NestedObjects(using=router.db_for_write(self.model))
        collector.collect([self.object])
        perms_needed = set()

        def format_callback(obj):

            p = '%s.%s' % (
                obj._meta.app_label,
                get_permission_codename('delete', obj._meta)
            )

            if not self.request.user.has_perm(p):
                perms_needed.add(obj._meta.verbose_name)

            registered = obj.__class__ in self.request.djangobmf_site.modules

            # only show bmf modules
            if not registered:
                return None

            if hasattr(obj, '_bmfmeta') and obj._bmfmeta.only_related:
                return format_html(
                    '{0}: {1}',
                    obj._meta.verbose_name,
                    obj
                )
            else:
                return format_html(
                    '{0}: <a href="{1}">{2}</a>',
                    obj._meta.verbose_name,
                    obj.bmfmodule_detail(),
                    obj
                )

        def format_protected_callback(obj):

            if obj.__class__ in self.request.djangobmf_site.modules and not obj._bmfmeta.only_related:
                return format_html(
                    '{0}: <a href="{1}">{2}</a>',
                    obj._meta.verbose_name,
                    obj.bmfmodule_detail(),
                    obj
                )
            else:
                return format_html(
                    '{0}: {1}',
                    obj._meta.verbose_name,
                    obj
                )

        to_delete = collector.nested(format_callback)

        protected = [
            format_protected_callback(obj) for obj in collector.protected
        ]

        return to_delete, perms_needed, protected
Example #43
0
def _nested_objs(obj):
    c = NestedObjects("default")
    c.collect([obj])

    def format_callback(obj):
        return mark_safe('<a href="/keys/{}/{}/">{}</a>'.format(obj._meta.model_name, obj.pk, escape(obj)))

    result = unordered_list(c.nested(format_callback))
    return mark_safe("<ul>{}</ul>".format(result))
Example #44
0
def list_deleted_objects(obj):
    model = obj.__class__
    def format_callback(item):
        return u'%s: %s' % (item._meta.verbose_name.capitalize(), force_unicode(item))

    collector = NestedObjects(using=router.db_for_write(model))
    collector.collect(model.objects.filter(id=obj.id))
    to_delete = collector.nested(format_callback)

    return {'to_delete': to_delete}
Example #45
0
def get_related_objects(obj, using=DEFAULT_DB_ALIAS):
    # This code is based on https://github.com/makinacorpus/django-safedelete
    collector = NestedObjects(using=using)
    collector.collect([obj])

    def flatten(elem):
        if isinstance(elem, list):
            return itertools.chain.from_iterable(map(flatten, elem))
        elif obj != elem:
            return (elem,)
        return ()

    return flatten(collector.nested())
Example #46
0
def get_merged_objects(objs, opts, user, admin_site, using):
    """
    Find all objects related to ``objs`` that should also be merged. ``objs``
    must be a homogenous iterable of objects (e.g. a QuerySet).

    Returns a nested list of strings suitable for display in the
    template with the ``unordered_list`` filter.

    """
    collector = NestedObjects(using=using)
    collector.collect(objs)
    perms_needed = set()

    def format_callback(obj):
        has_admin = obj.__class__ in admin_site._registry
        opts = obj._meta

        if has_admin:
            admin_url = reverse('%s:%s_%s_change'
                                % (admin_site.name,
                                   opts.app_label,
                                   opts.object_name.lower()),
                                None, (quote(obj._get_pk_val()),))
            p = '%s.%s' % (opts.app_label,
                           opts.get_delete_permission())
            if not user.has_perm(p):
                perms_needed.add(opts.verbose_name)
            p = '%s.%s' % (opts.app_label,
                           opts.get_change_permission())
            if not user.has_perm(p):
                perms_needed.add(opts.verbose_name)
            p = '%s.%s' % (opts.app_label,
                           opts.get_add_permission())
            if not user.has_perm(p):
                perms_needed.add(opts.verbose_name)
            # Display a link to the admin page.
            return mark_safe(u'%s: <a href="%s">%s</a>' %
                             (escape(capfirst(opts.verbose_name)),
                              admin_url,
                              escape(obj)))
        else:
            # Don't display link to edit, because it either has no
            # admin or is edited inline.
            return u'%s: %s' % (capfirst(opts.verbose_name),
                                force_text(obj))

    to_merge = collector.nested(format_callback)

    protected = [format_callback(obj) for obj in collector.protected]

    return to_merge, perms_needed, protected
Example #47
0
def related_objects(obj):
    """ Return a generator to the objects that would be deleted if we delete "obj" (excluding obj) """

    collector = NestedObjects(using=router.db_for_write(obj))
    collector.collect([obj])

    def flatten(elem):
        if isinstance(elem, list):
            return itertools.chain.from_iterable(map(flatten, elem))
        elif obj != elem:
            return (elem,)
        return ()

    return flatten(collector.nested())
Example #48
0
File: views.py Project: invliD/1327
def get_delete_cascade(request, title):
	document = get_object_or_error(Document, request.user, ['change_document'], url_title=title)

	collector = NestedObjects(using=DEFAULT_DB_ALIAS)
	collector.collect([document])
	delete_cascade = collector.nested()

	# remove all subclasses of current document from the list because that does not add much helpful information
	simplified_delete_cascade = []
	for cascade_item in delete_cascade:
		if issubclass(type(document), type(cascade_item)) and not type(document) == type(cascade_item):
			continue
		simplified_delete_cascade.append(cascade_item)

	return HttpResponse(json.dumps(delete_cascade_to_json(simplified_delete_cascade)))
Example #49
0
    def get_deleted_objects(objs, using):
        """
        Find all objects related to ``objs`` that should also be deleted.
        ``objs`` must be a homogeneous iterable of objects (e.g. a QuerySet).

        Returns a nested list of objects suitable for display in the
        template with the ``unordered_list`` filter.

        This is simplified from a method by the same name that the
        Django admin uses. "using" means the key in the DATABASES setting.
        """

        collector = NestedObjects(using=using)
        collector.collect(objs)
        # nested() can take a formatting callback if we want it later
        to_delete = collector.nested()
        return to_delete
Example #50
0
    def collect(self):
        def collect_objects(obj):
            try:
                iter(obj)
                for o in obj:
                    collect_objects(o)
            except TypeError:
                flattened.append(obj)

        collector = NestedObjects(using=self.using)
        collector.collect(self.qs)
        objs = collector.nested()
        flattened = []

        for obj in objs:
            collect_objects(obj)

        return flattened
Example #51
0
def get_deleted_objects(objs, user):
    """
    Find all objects related to ``objs`` that should also be deleted. ``objs``
    must be a homogeneous iterable of objects (e.g. a QuerySet).

    Returns a nested list of strings suitable for display in the
    template with the ``unordered_list`` filter.

    Copied and updated from django.contrib.admin.utils for front end display.
    """
    using = router.db_for_write(objs[0].__class__)
    collector = NestedObjects(using=using)
    collector.collect(objs)
    perms_needed = set()

    def format_callback(obj):
        opts = obj._meta

        no_edit_link = '%s: %s' % (capfirst(opts.verbose_name),
                                   force_text(obj))

        p = '%s.%s' % (opts.app_label,
                           get_permission_codename('delete', opts))
        if not user.has_perm(p):
            perms_needed.add(opts.verbose_name)

        if hasattr(obj, 'get_absolute_url'):
            url = obj.get_absolute_url()
            # Display a link to the admin page.
            return format_html('{}: <a href="{}">{}</a>',
                               capfirst(opts.verbose_name),
                               url,
                               obj)
        else:
            # Don't display link to edit, because it either has no
            # admin or is edited inline.
            return no_edit_link

    to_delete = collector.nested(format_callback)

    protected = [format_callback(obj) for obj in collector.protected]

    return to_delete, collector.model_count, perms_needed, protected
Example #52
0
def collect_backlinks(model_instance):
    """:param model_instance: Django Model Instance
    :return: A dict of Models that reference the current
    Useful for determining if an instance can be deleted.  Includes hyperlinks to the related models
    """
    from django.contrib.admin.utils import NestedObjects
    collector = NestedObjects(using='scenario_db')  # or specific database
    collector.collect([model_instance])  # https://docs.djangoproject.com/en/1.7/releases/1.7/#remove-and-clear-methods-of-related-managers
    dependants = collector.nested()  # fun fact: spelling differs between America and Brittain
    #print("Found related models:", dependants)
    links = {}
    if len(dependants[1:]):
        for direct_reference in dependants[1:][0]:  # only iterates over the top level
            if not isinstance(direct_reference, list) and not isinstance(direct_reference, RelationalPoint):  # Points are obvious, don't include them
                name = direct_reference.__class__.__name__
                try:  # not everything has a name attr
                    links[str(direct_reference)] = '/setup/%s/%i/' % (name, direct_reference.pk)
                except:
                    links['%s:%i' % (name, direct_reference.pk)] = '/setup/%s/%i/' % (name, direct_reference.pk)
    #print(links)
    return links
Example #53
0
def collect_deleted_objects(modeladmin, request, queryset):
    """Collects objects that are related to queryset items and checks
       their permissions.

       This method checks if the user has permissions to delete items that are
       anyhow related to theese in the queryset (regardless of the depth).

       ``modeladmin`` is expected to be a ModelAdmin instance corresponding
       to the class of items contained in the ``queryset``.
    """
    db_backend = router.db_for_write(queryset.first().__class__)
    # NestedObjects is undocumented API, can blow up at any time
    collector = NestedObjects(using=db_backend)
    collector.collect(queryset)

    # Check permissions and return a human-readable string representation
    perms_needed = set()

    def format_callback(obj):
        admin_site = modeladmin.admin_site
        has_admin = obj.__class__ in admin_site._registry
        opts = obj._meta

        if has_admin:
            model_admin = admin_site._registry[obj.__class__]
            if not request.user.is_superuser and \
                    not model_admin.has_delete_permission(request, obj):
                perms_needed.add(opts.verbose_name)

        return '%s: %s' % (capfirst(opts.verbose_name),
                           force_text(obj))

    # Get a nested list of dependent objects
    to_delete = collector.nested(format_callback)

    protected = [format_callback(obj) for obj in collector.protected]

    return to_delete, perms_needed, protected
Example #54
0
def delete_related_objects(modeladmin, request, queryset):
    """
    Action that deletes related objects for the selected items.

    This action first displays a confirmation page whichs shows all the
    deleteable objects, or, if the user has no permission one of the related
    childs (foreignkeys), a "permission denied" message.

    Next, it deletes all related objects and redirects back to the change list.
    """
    opts = modeladmin.model._meta
    app_label = opts.app_label

    # Check that the user has delete permission for the actual model
    if not modeladmin.has_delete_permission(request):
        raise PermissionDenied

    using = router.db_for_write(modeladmin.model)

    first_level_related_objects = []
    collector = NestedObjects(using=using)
    collector.collect(queryset)
    for base_object_or_related_list in collector.nested():
        if type(base_object_or_related_list) is not list:
            # If it's not a list, it's a base object. Skip it.
            continue
        for obj in base_object_or_related_list:
            if type(obj) is list:
                # A list here contains related objects for the previous
                # element. We can skip it since delete() on the first
                # level of related objects will cascade.
                continue
            elif not isinstance(obj, _ReadOnlyModel):
                first_level_related_objects.append(obj)

    # Populate deletable_objects, a data structure of (string representations
    # of) all related objects that will also be deleted.
    deletable_objects, model_count, perms_needed, protected = get_deleted_objects(
        first_level_related_objects, opts, request.user,
        modeladmin.admin_site, using
    )

    # The user has already confirmed the deletion.
    # Do the deletion and return a None to display the change list view again.
    if request.POST.get('post'):
        if perms_needed:
            raise PermissionDenied
        n = 0
        with transaction.atomic(using):
            for obj in first_level_related_objects:
                obj_display = force_text(obj)
                modeladmin.log_deletion(request, obj, obj_display)
                obj.delete()
                n += 1
        modeladmin.message_user(
            request,
            _("Successfully deleted %(count)d related objects.") % {
                "count": n, "items": model_ngettext(modeladmin.opts, n)},
            messages.SUCCESS
        )
        # Return None to display the change list page again.
        return None

    if len(queryset) == 1:
        objects_name = force_text(opts.verbose_name)
    else:
        objects_name = force_text(opts.verbose_name_plural)

    if perms_needed or protected:
        title = _("Cannot delete %(name)s") % {"name": objects_name}
    else:
        title = _("Are you sure?")

    context = dict(
        modeladmin.admin_site.each_context(request),
        title=title,
        objects_name=objects_name,
        deletable_objects=[deletable_objects],
        model_count=dict(model_count).items(),
        queryset=queryset,
        perms_lacking=perms_needed,
        protected=protected,
        opts=opts,
        action_checkbox_name=helpers.ACTION_CHECKBOX_NAME,
    )

    request.current_app = modeladmin.admin_site.name

    # Display the confirmation page
    return TemplateResponse(
        request, "delete_related_for_selected_confirmation.html",
        context, current_app=modeladmin.admin_site.name)
Example #55
0
 def _collect_related(self, obj):
     collector = NestedObjects(using=DEFAULT_DB_ALIAS)
     collector.collect([obj])
     collected = collector.nested()
     return u''.join(self._collect_related_format(collected))
Example #56
0
def get_dep_objects(instance, using=DEFAULT_DB_ALIAS):
    """
    Find all objects related to ``objs`` that should also be deleted. ``objs``
    must be a homogeneous iterable of objects (e.g. a QuerySet).

    Returns a nested list of strings suitable for display in the
    template with the ``unordered_list`` filter.

    """
    collector = NestedObjects(using=using)
    collector.collect([instance])

    def format_callback(obj):
        no_edit_link = '%s: %s' % (capfirst(force_text(obj._meta.verbose_name)),
                                   force_text(obj))
        return no_edit_link

    def format_callback2(obj):
        no_edit_link = '%s' % (capfirst(force_text(obj._meta.verbose_name)))
        return no_edit_link

    #ver_objs = collector.nested(format_callback)
    objects = collector.nested()
    # print objects

    deps = []

    try:
        for x in objects[1]:
            if type(x) is not list:
                deps.append(x)
    except:
        pass

    # obteniendo mensaje para eliminar

    msg_del = ''

    if deps:
        objs = []
        for p in deps:
            if not 'relationship' in force_text(p._meta.verbose_name):
                objs.append(
                    _(u'<br>%(class_name)s: "%(instance)s"') % {
                        'class_name': capfirst(force_text(p._meta.verbose_name)),
                        'instance': force_text(p) + ' (' + force_text(p.pk) + ')'}
                )
        params = {
            'class_name': capfirst(force_text(instance._meta.verbose_name)),
            'instance': force_text(instance),
            'related_objects': get_text_list(objs, _('and'))}
        msg = _("Deleting %(class_name)s %(instance)s would require deleting the following "
                "protected related objects: %(related_objects)s")
        msgx = _("Deleting the %(object_name)s '%(escaped_object)s' would require deleting the "
                "following protected related objects:")
        #raise ValidationError(force_text(msg), code='deleting_protected', params=params)
        #raise Exception(msg)
        # messages.success(self.request, (', ').join(deps)# )
        msg_del = force_text(msg % params)

        msg_delx = msgx % {
            'object_name': capfirst(force_text(instance._meta.verbose_name)),
            'escaped_object': get_text_list(objs, _('and'))}

    return deps, msg_del
Example #57
0
def delete_related_services(modeladmin, request, queryset):
    opts = modeladmin.model._meta
    app_label = opts.app_label
    
    using = router.db_for_write(modeladmin.model)
    collector = NestedObjects(using=using)
    collector.collect(queryset)
    registered_services = services.get()
    related_services = []
    to_delete = []
    
    admin_site = modeladmin.admin_site
    
    def format(obj, account=False):
        has_admin = obj.__class__ in admin_site._registry
        opts = obj._meta
        no_edit_link = '%s: %s' % (capfirst(opts.verbose_name), force_text(obj))
        
        if has_admin:
            try:
                admin_url = reverse(
                    'admin:%s_%s_change' % (opts.app_label, opts.model_name),
                    None, (quote(obj._get_pk_val()),)
                )
            except NoReverseMatch:
                # Change url doesn't exist -- don't display link to edit
                return no_edit_link
            
            # Display a link to the admin page.
            context = (capfirst(opts.verbose_name), admin_url, obj)
            if account:
                context += (_("services to delete:"),)
                return format_html('{} <a href="{}">{}</a> {}', *context)
            return format_html('{}: <a href="{}">{}</a>', *context)
        else:
            # Don't display link to edit, because it either has no
            # admin or is edited inline.
            return no_edit_link
    
    def format_nested(objs, result):
        if isinstance(objs, list):
            current = []
            for obj in objs:
                format_nested(obj, current)
            result.append(current)
        else:
            result.append(format(objs))
    
    for nested in collector.nested():
        if isinstance(nested, list):
            # Is lists of objects
            current = []
            is_service = False
            for service in nested:
                if type(service) in registered_services:
                    if service == main_systemuser:
                        continue
                    current.append(format(service))
                    to_delete.append(service)
                    is_service = True
                elif is_service and isinstance(service, list):
                    nested = []
                    format_nested(service, nested)
                    current.append(nested)
                    is_service = False
                else:
                    is_service = False
            related_services.append(current)
        elif isinstance(nested, modeladmin.model):
            # Is account
            # Prevent the deletion of the main system user, which will delete the account
            main_systemuser = nested.main_systemuser
            related_services.append(format(nested, account=True))
    
    # The user has already confirmed the deletion.
    # Do the deletion and return a None to display the change list view again.
    if request.POST.get('post'):
        accounts = len(queryset)
        msg = _("Related services deleted and account disabled.")
        for account in queryset:
            account.is_active = False
            account.save(update_fields=('is_active',))
            modeladmin.log_change(request, account, msg)
        if accounts:
            relateds = len(to_delete)
            for obj in to_delete:
                obj_display = force_text(obj)
                modeladmin.log_deletion(request, obj, obj_display)
                obj.delete()
            context = {
                'accounts': accounts,
                'relateds': relateds,
            }
            msg = _("Successfully disabled %(accounts)d account and deleted %(relateds)d related services.") % context
            modeladmin.message_user(request, msg, messages.SUCCESS)
        # Return None to display the change list page again.
        return None
    
    if len(queryset) == 1:
        objects_name = force_text(opts.verbose_name)
    else:
        objects_name = force_text(opts.verbose_name_plural)
    
    context = dict(
        admin_site.each_context(request),
        title=_("Are you sure?"),
        objects_name=objects_name,
        deletable_objects=[related_services],
        model_count=dict(collector.model_count).items(),
        queryset=queryset,
        opts=opts,
        action_checkbox_name=helpers.ACTION_CHECKBOX_NAME,
    )
    request.current_app = admin_site.name
    # Display the confirmation page
    template = 'admin/%s/%s/delete_related_services_confirmation.html' % (app_label, opts.model_name)
    return TemplateResponse(request, template, context)
Example #58
0
def delete_related_services(modeladmin, request, queryset):
    opts = modeladmin.model._meta
    app_label = opts.app_label
    
    using = router.db_for_write(modeladmin.model)
    collector = NestedObjects(using=using)
    collector.collect(queryset)
    registered_services = services.get()
    related_services = []
    to_delete = []
    
    user = request.user
    admin_site = modeladmin.admin_site
    
    def format(obj, account=False):
        has_admin = obj.__class__ in admin_site._registry
        opts = obj._meta
        no_edit_link = '%s: %s' % (capfirst(opts.verbose_name), force_text(obj))
        
        if has_admin:
            try:
                admin_url = reverse('admin:%s_%s_change' % (opts.app_label, opts.model_name),
                        None, (quote(obj._get_pk_val()),)
                )
            except NoReverseMatch:
                # Change url doesn't exist -- don't display link to edit
                return no_edit_link
            
            p = '%s.%s' % (opts.app_label, get_permission_codename('delete', opts))
            if not user.has_perm(p):
                perms_needed.add(opts.verbose_name)
            # Display a link to the admin page.
            context = (capfirst(opts.verbose_name), admin_url, obj)
            if account:
                context += (_("services to delete:"),)
                return format_html('{} <a href="{}">{}</a> {}', *context)
            return format_html('{}: <a href="{}">{}</a>', *context)
        else:
            # Don't display link to edit, because it either has no
            # admin or is edited inline.
            return no_edit_link
    
    def format_nested(objs, result):
        if isinstance(objs, list):
            current = []
            for obj in objs:
                format_nested(obj, current)
            result.append(current)
        else:
            result.append(format(objs))
    
    for nested in collector.nested():
        if isinstance(nested, list):
            # Is lists of objects
            current = []
            is_service = False
            for service in nested:
                if type(service) in registered_services:
                    if service == main_systemuser:
                        continue
                    current.append(format(service))
                    to_delete.append(service)
                    is_service = True
                elif is_service and isinstance(service, list):
                    nested = []
                    format_nested(service, nested)
                    current.append(nested)
                    is_service = False
                else:
                    is_service = False
            related_services.append(current)
        elif isinstance(nested, modeladmin.model):
            # Is account
            # Prevent the deletion of the main system user, which will delete the account
            main_systemuser = nested.main_systemuser
            related_services.append(format(nested, account=True))
    
    # The user has already confirmed the deletion.
    # Do the deletion and return a None to display the change list view again.
    if request.POST.get('post'):
        n = queryset.count()
        if n:
            for obj in to_delete:
                obj_display = force_text(obj)
                modeladmin.log_deletion(request, obj, obj_display)
                # TODO This probably will fail in certain conditions, just capture exception
                obj.delete()
            modeladmin.message_user(request, _("Successfully deleted %(count)d %(items)s.") % {
                "count": n, "items": model_ngettext(modeladmin.opts, n)
            }, messages.SUCCESS)
        # Return None to display the change list page again.
        return None
    
    if len(queryset) == 1:
        objects_name = force_text(opts.verbose_name)
    else:
        objects_name = force_text(opts.verbose_name_plural)
    
    context = dict(
        modeladmin.admin_site.each_context(request),
        title=_("Are you sure?"),
        objects_name=objects_name,
        deletable_objects=[related_services],
        model_count=dict(collector.model_count).items(),
        queryset=queryset,
        opts=opts,
        action_checkbox_name=helpers.ACTION_CHECKBOX_NAME,
    )
    request.current_app = modeladmin.admin_site.name
    # Display the confirmation page
    return TemplateResponse(request, modeladmin.delete_selected_confirmation_template or [
        "admin/%s/%s/delete_selected_confirmation.html" % (app_label, opts.model_name),
        "admin/%s/delete_selected_confirmation.html" % app_label,
        "admin/delete_selected_confirmation.html"
    ], context)