Skip to content

Commit

Permalink
Merge branch 'gcrahay-fix_127'
Browse files Browse the repository at this point in the history
  • Loading branch information
gaelmuller committed Jan 14, 2017
2 parents 242394b + 1fbb7e0 commit bb68a82
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 31 deletions.
32 changes: 27 additions & 5 deletions fir_artifacts/artifacts.py
Expand Up @@ -38,7 +38,7 @@ def incs_for_art(art_string):
return incs


def all_for_object(obj, raw=False):
def all_for_object(obj, raw=False, user=None):
result = []
total_count = 0
correlated_count = 0
Expand All @@ -48,7 +48,7 @@ def all_for_object(obj, raw=False):

for artifact in INSTALLED_ARTIFACTS:
values = obj.artifacts.filter(type=artifact)
artifact_collection = INSTALLED_ARTIFACTS[artifact](values, obj)
artifact_collection = INSTALLED_ARTIFACTS[artifact](values, obj, user=user)
total_count += values.count()
correlated_count += artifact_collection.correlated_count()
result.append(artifact_collection)
Expand Down Expand Up @@ -76,13 +76,34 @@ def after_save(cls, value, event):
# Do nothing, allows for specific callback in subclasses
pass

def __init__(self, artifacts, event):
self._artifacts = artifacts
def __init__(self, artifacts, event, user=None):
class ArtifactDisplay(object):
def __init__(self, artifact, user):
self.artifact = artifact
self.correlation_count = self.artifact.relations_for_user(user).count()

@property
def value(self):
return self.artifact.value

@property
def type(self):
return self.artifact.type

@property
def id(self):
return self.artifact.id

@property
def pk(self):
return self.artifact.pk

self._artifacts = [ArtifactDisplay(artifact, user) for artifact in artifacts]
self._event = event

self._correlated = []
for artifact in self._artifacts:
if artifact.relations.count() > 1:
if artifact.correlation_count > 1:
self._correlated.append(artifact)

def json(self, request):
Expand All @@ -96,6 +117,7 @@ def display(self, request, correlated=False, json=False):
context['artifact_values'] = self._correlated
else:
context['artifact_values'] = self._artifacts

context['event'] = self._event

if not json:
Expand Down
4 changes: 2 additions & 2 deletions fir_artifacts/templates/fir_artifacts/default.html
Expand Up @@ -6,12 +6,12 @@
<td>
{% for a in artifact_values %}
<a
{% if a.relations.count > 1 %} class='multiple' {% endif %}
{% if a.correlation_count > 1 %} class='multiple' {% endif %}
href="{% url 'artifacts:correlations' a.id %}" data-id="{{ a.id }}"
>
{{ a.value }}
</a>
{% if a.relations.count > 1 %} ({{ a.relations.count }}) {% endif %}
{% if a.correlation_count > 1 %} ({{ a.correlation_count }}) {% endif %}
{% has_perm 'incidents.handle_incidents' obj=event as can_handle_incident %}
{% if can_handle_incident %}
<form class='icon' action="{% url 'artifacts:detach' a.id event|relation_name event.id %}" method='POST'>
Expand Down
4 changes: 3 additions & 1 deletion fir_artifacts/views.py
Expand Up @@ -14,7 +14,9 @@
@user_passes_test(is_incident_viewer)
def artifacts_correlations(request, artifact_id):
a = get_object_or_404(Artifact, pk=artifact_id)
correlations = a.relations.group()
correlations = a.relations_for_user(request.user).group()
if all([not link_type.objects.exists() for link_type in correlations.values()]):
raise PermissionDenied
return render(request, 'fir_artifacts/correlation_list.html', {'correlations': correlations,
'artifact': a,
'incident_show_id': settings.INCIDENT_SHOW_ID})
Expand Down
27 changes: 22 additions & 5 deletions fir_plugins/managers.py
Expand Up @@ -3,21 +3,33 @@


class LinkableManager(BaseManager):
def __init__(self, instance):
def __init__(self, instance, user=None, permission='incidents.view_incidents'):
self.linkable = instance
self.user = user
self.permission = permission

def get_querysets(self, linked_type=None):
qss = list()
if not linked_type:
for link_name, linked_model in getattr(self.linkable, "_LINKS", dict()).items():
if hasattr(self.linkable, link_name):
qss.append(getattr(self.linkable, link_name).all())
if hasattr(linked_model.model, 'authorization') and self.user is not None:
qss.append(
linked_model.model.authorization.for_user(self.user, self.permission).filter(
**{linked_model.reverse_link_name: self.linkable.pk}))
else:
qss.append(getattr(self.linkable, link_name).all())
else:
if not isinstance(linked_type, (list, tuple)):
linked_type = [linked_type,]
for link_name, linked_model in getattr(self.linkable, "_LINKS", dict()).items():
if linked_type.count(linked_model.model) > 0:
qss.append(getattr(self.linkable, link_name).all())
if hasattr(linked_model.model, 'authorization') and self.user is not None:
qss.append(
linked_model.model.authorization.for_user(self.user, self.permission).filter(
**{linked_model.reverse_link_name: self.linkable.pk}))
else:
qss.append(getattr(self.linkable, link_name).all())
return QuerySetSequence(*qss)

def all(self, linked_type=None):
Expand All @@ -32,8 +44,13 @@ def __init__(self, linked, objects):
self.objects = objects

for link_name, linked_model in getattr(self.linkable, "_LINKS", dict()).items():
objects = getattr(self.linkable, link_name).all()
result[link_name] = Group(linked_model, objects)
if hasattr(self.linkable, link_name):
if hasattr(linked_model.model, 'authorization') and self.user is not None:
objects = linked_model.model.authorization.for_user(self.user, self.permission).filter(
**{linked_model.reverse_link_name: self.linkable.pk})
else:
objects = getattr(self.linkable, link_name).all()
result[link_name] = Group(linked_model, objects)
return result

def count(self, linked_type=None):
Expand Down
11 changes: 9 additions & 2 deletions fir_plugins/models.py
Expand Up @@ -54,6 +54,11 @@ def relations(self):
self._relation_manager = LinkableManager(self)
return self._relation_manager

def relations_for_user(self, user):
if user is None:
return self.relations
return LinkableManager(self, user=user)

@classmethod
def link_to(cls, linked_model, link_name=None, verbose_name=None, verbose_name_plural=None):
return create_link(cls, linked_model)
Expand All @@ -65,9 +70,10 @@ class Meta:
def create_link(linkable_model, linked_model, linkable_link_name=None, verbose_name=None, verbose_name_plural=None):

class LinkedModel(object):
def __init__(self, model, link_name=None, verbose_name=None, verbose_name_plural=None):
def __init__(self, model, link_name=None, verbose_name=None, verbose_name_plural=None, reverse_link_name=None):
self.model = model
self.link_name = link_name
self.reverse_link_name = reverse_link_name
self.verbose_name = verbose_name
self.verbose_name_plural = verbose_name_plural

Expand Down Expand Up @@ -103,7 +109,8 @@ def __init__(self, model, link_name=None, verbose_name=None, verbose_name_plural
linkable_model._LINKS[linkable_link_name] = LinkedModel(
linked_model, link_name=linkable_link_name,
verbose_name=verbose_name,
verbose_name_plural=verbose_name_plural)
verbose_name_plural=verbose_name_plural,
reverse_link_name=linked_link_name)
return linkable_model


Expand Down
51 changes: 51 additions & 0 deletions fir_relations/locale/fr/LC_MESSAGES/django.po
@@ -0,0 +1,51 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-01-12 18:17+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"

#: models.py:66
msgid "Incident"
msgstr ""

#: models.py:67
msgid "Event"
msgstr ""

#: templates/fir_relations/relations_sidebar.html:2
msgid "References"
msgstr "Référence"

#: templates/fir_relations/relations_sidebar.html:3
msgid "Referenced by"
msgstr "Référencé par"

#: templates/fir_relations/sidebar.html:8
msgid "ID"
msgstr ""

#: templates/fir_relations/sidebar.html:9
msgid "Type"
msgstr ""

#: templates/fir_relations/sidebar.html:10
msgid "Subject"
msgstr ""

#: templates/fir_relations/sidebar.html:27
msgid "Remove relation"
msgstr "Retirer la relation"
23 changes: 20 additions & 3 deletions fir_relations/models.py
Expand Up @@ -14,13 +14,28 @@

@python_2_unicode_compatible
class TemplateRelation(object):
def __init__(self, relation, relation_type='target'):
def __init__(self, relation, request, relation_type='target'):
self.relation = relation
self.relation_type = relation_type
self.user = request.user
if self.relation_type == 'target':
self.object = relation.target
else:
self.object = relation.source
self._check_permission()

def _check_permission(self):
self.can_view = False
self.can_edit = False
if hasattr(self.object, 'has_perm'):
if self.object.has_perm(self.user, 'incidents.view_incidents'):
self.can_view = True
else:
return
if hasattr(self.relation.source, 'has_perm'):
if self.relation.source.has_perm(self.user, 'incidents.handle_incidents'):
self.can_edit = True


@property
def url(self):
Expand Down Expand Up @@ -79,10 +94,12 @@ def update_relations(self, source_instance, data):
relations.append(relation)
return relations

def as_template_objects(self, relation_type='target'):
def as_template_objects(self, request, relation_type='target'):
relations = []
for relation in self:
relations.append(TemplateRelation(relation, relation_type=relation_type))
template_relation = TemplateRelation(relation, request, relation_type=relation_type)
if template_relation.can_view:
relations.append(template_relation)
return relations


Expand Down
10 changes: 6 additions & 4 deletions fir_relations/templates/fir_relations/sidebar.html
Expand Up @@ -21,10 +21,12 @@ <h4 class='widget'>{{ title }}</h4>
</a>
</td>
<td class="icon-column">
<form id='delete_relation_{{relation.relation.id}}' name='delete' action="{% url 'relations:remove' relation.relation.id %}" method='POST' data-ajaxform data-action='remove' data-target='#relation_id_{{relation.relation.id}}'>
{% csrf_token %}
<button type='submit' class='btn btn-xs btn-link icon'><i class='glyphicon glyphicon-remove'></i></button>
</form>
{% if relation.can_edit %}
<form id='delete_relation_{{relation.relation.id}}' name='delete' action="{% url 'relations:remove' relation.relation.id %}" method='POST' data-ajaxform data-action='remove' data-target='#relation_id_{{relation.relation.id}}'>
{% csrf_token %}
<button type='submit' class='btn btn-xs btn-link icon' title="{% trans 'Remove relation' %}"><i class='glyphicon glyphicon-remove'></i></button>
</form>
{% endif %}
</td>
</tr>
{% endfor %}
Expand Down
18 changes: 11 additions & 7 deletions fir_relations/views.py
@@ -1,22 +1,23 @@
from json import dumps

from django.contrib.auth.decorators import login_required, user_passes_test
from django.core.exceptions import PermissionDenied
from django.http import HttpResponse
from django.shortcuts import render, get_object_or_404

from fir_relations.models import Relation
from incidents.views import is_incident_handler
from incidents.views import is_incident_handler, is_incident_viewer


@login_required
@user_passes_test(is_incident_handler)
@user_passes_test(is_incident_viewer)
def relations(request, content_type, object_id):
references = Relation.objects.filter(src_content_type=content_type,
src_object_id=object_id,
active=True).as_template_objects(relation_type='target')
active=True).as_template_objects(request, relation_type='target')
referenced_by = Relation.objects.filter(tgt_content_type=content_type,
tgt_object_id=object_id,
active=True).as_template_objects(relation_type='source')
active=True).as_template_objects(request, relation_type='source')
return render(request, "fir_relations/relations_sidebar.html",
{'references': references, 'referenced_by': referenced_by})

Expand All @@ -26,6 +27,9 @@ def relations(request, content_type, object_id):
def remove_relation(request, relation_id):
if request.method == "POST":
relation = get_object_or_404(Relation, pk=relation_id)
relation.active = False
relation.save()
return HttpResponse(dumps({'status': 'success'}), content_type="application/json")
if hasattr(relation.source, 'has_perm') and \
relation.source.has_perm(request.user, 'incidents.handle_incidents'):
relation.active = False
relation.save()
return HttpResponse(dumps({'status': 'success'}), content_type="application/json")
raise PermissionDenied
4 changes: 2 additions & 2 deletions incidents/views.py
Expand Up @@ -29,7 +29,7 @@
from json import dumps
from django.template import Template

from django.core.exceptions import ObjectDoesNotExist
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from django.forms.models import model_to_dict, modelform_factory
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
Expand Down Expand Up @@ -219,7 +219,7 @@ def details(request, incident_id, authorization_target=None):
form.fields['action'].queryset = Label.objects.filter(group__name='action').exclude(
name__in=['Closed', 'Opened', 'Blocked'])

(artifacts, artifacts_count, correlated_count) = libartifacts.all_for_object(i)
(artifacts, artifacts_count, correlated_count) = libartifacts.all_for_object(i, user=request.user)

"""
Temp fix until i figure out how to set this
Expand Down

0 comments on commit bb68a82

Please sign in to comment.