Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement dynamic settings in labels, make SeverityChoice labels #320

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ services:
context: ../
dockerfile: docker/Dockerfile
entrypoint: /bin/sh
command: -c "wait-for -t 10 fir_db:3306 && python manage.py makemigrations && python manage.py migrate && python manage.py loaddata incidents/fixtures/*.json && python manage.py collectstatic --no-input && python manage.py runserver 0.0.0.0:8000"
command: -c "wait-for -t 20 fir_db:3306 && python manage.py makemigrations && python manage.py migrate && python manage.py loaddata incidents/fixtures/*.json && python manage.py collectstatic --no-input && python manage.py runserver 0.0.0.0:8000"
container_name: fir
hostname: fir
depends_on:
Expand Down Expand Up @@ -58,7 +58,7 @@ services:
fir_celery_worker:
image: fir:latest
entrypoint: /bin/sh
command: -c "wait-for -t 10 fir_redis:6379 && wait-for -t 30 fir:8000 -- celery -A fir_celery.celeryconf.celery_app worker -l debug"
command: -c "wait-for -t 20 fir_redis:6379 && wait-for -t 40 fir:8000 -- celery -A fir_celery.celeryconf.celery_app worker -l debug"
container_name: fir_celery_worker
hostname: fir_celery_worker
depends_on:
Expand All @@ -73,7 +73,7 @@ services:
fir_celery_beat:
image: fir:latest
entrypoint: /bin/sh
command: -c "wait-for -t 10 fir_redis:6379 && wait-for -t 30 fir:8000 -- celery -A fir_celery.celeryconf.celery_app beat -l debug"
command: -c "wait-for -t 20 fir_redis:6379 && wait-for -t 40 fir:8000 -- celery -A fir_celery.celeryconf.celery_app beat -l debug"
container_name: fir_celery_beat
hostname: fir_celery_beat
depends_on:
Expand Down
2 changes: 2 additions & 0 deletions fir/config/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,5 @@
# HTTP_X_API == "X-Api" in HTTP headers.
'TOKEN_AUTHENTICATION_META': 'HTTP_X_API',
}

DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
11 changes: 10 additions & 1 deletion fir_api/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from incidents.models import (
Incident,
Label,
LabelGroup,
IncidentCategory,
Comments,
File,
Expand Down Expand Up @@ -125,10 +126,18 @@ class LabelFilter(FilterSet):

id = NumberFilter(field_name="id")
name = CharFilter(field_name="name")
group = ModelChoiceFilter(
to_field_name="name",
field_name="group__name",
queryset=LabelGroup.objects.all(),
)
color = CharFilter(
field_name="dynamic_config__color", lookup_expr="icontains", label="color"
)

class Meta:
model = Label
fields = ["id", "name", "group"]
fields = ["id", "name", "group", "color"]


class ValidAttributeFilter(FilterSet):
Expand Down
10 changes: 9 additions & 1 deletion fir_api/permissions.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from rest_framework.permissions import BasePermission
from rest_framework.permissions import BasePermission, IsAdminUser, SAFE_METHODS
from incidents.models import Incident, AccessControlEntry


Expand Down Expand Up @@ -33,3 +33,11 @@ def has_object_permission(self, request, view, obj):
return True
except:
return False


class IsAdminUserOrReadOnly(IsAdminUser):
def has_permission(self, request, view):
is_admin = super().has_permission(request, view)
is_read = bool(request.method in SAFE_METHODS)

return request.user.is_authenticated and is_read or is_admin
14 changes: 10 additions & 4 deletions fir_api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@
Incident,
Artifact,
Label,
LabelGroup,
File,
IncidentCategory,
BusinessLine,
Comments,
Attribute,
ValidAttribute,
SeverityChoice,
STATUS_CHOICES,
CONFIDENTIALITY_LEVEL,
PrettyJSONEncoder,
)

if apps.is_installed("fir_todos"):
Expand Down Expand Up @@ -113,11 +114,16 @@ class Meta:


class LabelSerializer(serializers.ModelSerializer):
group = serializers.SlugRelatedField(many=False, read_only=True, slug_field="name")
group = serializers.SlugRelatedField(
many=False,
queryset=LabelGroup.objects.all(),
slug_field="name",
)
dynamic_config = serializers.JSONField(encoder=PrettyJSONEncoder, initial={})

class Meta:
model = Label
fields = ("id", "name", "group")
fields = ("id", "name", "group", "dynamic_config")
read_only_fields = ("id",)


Expand Down Expand Up @@ -216,7 +222,7 @@ class IncidentSerializer(serializers.ModelSerializer):
)
severity = serializers.SlugRelatedField(
slug_field="name",
queryset=SeverityChoice.objects.all(),
queryset=Label.objects.filter(group__name="severity"),
required=True,
)
category = serializers.SlugRelatedField(
Expand Down
2 changes: 1 addition & 1 deletion fir_api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
router.register(r"artifacts", views.ArtifactViewSet)
router.register(r"files", views.FileViewSet)
router.register(r"comments", views.CommentViewSet)
router.register(r"labels", views.LabelViewSet)
router.register(r"labels", views.LabelViewSet, basename="labels")
router.register(r"attributes", views.AttributeViewSet)
router.register(r"validattributes", views.ValidAttributeViewSet)
router.register(r"businesslines", views.BusinessLinesViewSet)
Expand Down
37 changes: 24 additions & 13 deletions fir_api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from rest_framework import renderers
from rest_framework.response import Response
from rest_framework.filters import OrderingFilter
from rest_framework.serializers import ValidationError
from django_filters.rest_framework import (
DjangoFilterBackend,
FilterSet,
Expand Down Expand Up @@ -58,7 +59,7 @@
ValidAttributeFilter,
FileFilter,
)
from fir_api.permissions import IsIncidentHandler
from fir_api.permissions import IsIncidentHandler, IsAdminUserOrReadOnly
from fir_artifacts.files import handle_uploaded_file, do_download
from fir_artifacts.models import Artifact, File
from incidents.models import (
Expand Down Expand Up @@ -132,7 +133,7 @@ def get_businesslines(self, businesslines):
def perform_create(self, serializer):
opened_by = self.request.user
serializer.is_valid(raise_exception=True)
if type(self.request.data).__name__ == 'dict':
if type(self.request.data).__name__ == "dict":
bls = self.request.data.get("concerned_business_lines", [])
else:
bls = self.request.data.getlist("concerned_business_lines", [])
Expand All @@ -153,7 +154,7 @@ def perform_update(self, serializer):
Comments.create_diff_comment(
self.get_object(), serializer.validated_data, self.request.user
)
if type(self.request.data).__name__ == 'dict':
if type(self.request.data).__name__ == "dict":
bls = self.request.data.get("concerned_business_lines", [])
else:
bls = self.request.data.getlist("concerned_business_lines", [])
Expand Down Expand Up @@ -237,19 +238,31 @@ def perform_destroy(self, instance):
return super().perform_destroy(instance)


class LabelViewSet(ListModelMixin, viewsets.GenericViewSet):
class LabelViewSet(viewsets.ModelViewSet):
"""
API endpoint for viewing labels
"""

queryset = Label.objects.all()
queryset = Label.objects.all().order_by('id')
serializer_class = LabelSerializer
permission_classes = (IsAuthenticated,)
permission_classes = (IsAdminUserOrReadOnly,)
filter_backends = [DjangoFilterBackend]
filterset_class = LabelFilter

def get_queryset(self):
return super().get_queryset()
def perform_update(self, serializer):
self.perform_create(serializer)

def perform_create(self, serializer):
if serializer.is_valid():
try:
serializer.Meta.model.validate_dynamic_config(
serializer.validated_data["name"],
serializer.validated_data["group"],
serializer.validated_data["dynamic_config"],
)
except Exception as e:
raise ValidationError(e.message)
serializer.save()


class FileViewSet(ListModelMixin, RetrieveModelMixin, viewsets.GenericViewSet):
Expand Down Expand Up @@ -287,12 +300,12 @@ def upload(self, request, pk):
pk=pk,
)
files_added = []
if type(self.request.data).__name__ == 'dict':
if type(self.request.data).__name__ == "dict":
uploaded_files = request.FILES.get("file", [])
else:
uploaded_files = request.FILES.getlist("file", [])

if type(self.request.data).__name__ == 'dict':
if type(self.request.data).__name__ == "dict":
descriptions = request.data.get("description", [])
else:
descriptions = request.data.getlist("description", [])
Expand All @@ -303,9 +316,7 @@ def upload(self, request, pk):
status=status.HTTP_400_BAD_REQUEST,
)

for uploaded_file, description in zip(
uploaded_files, descriptions
):
for uploaded_file, description in zip(uploaded_files, descriptions):
file_wrapper = FileWrapper(uploaded_file.file)
file_wrapper.name = uploaded_file.name
file = handle_uploaded_file(file_wrapper, description, incident)
Expand Down
8 changes: 6 additions & 2 deletions incidents/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,22 @@ class BusinessLineAdmin(TreeAdmin):
class IncidentAdmin(admin.ModelAdmin):
exclude = ("artifacts", )

class LabelAdmin(admin.ModelAdmin):
class Media:
js = ("colorfield/jscolor/jscolor.js", "custom_js/admin_labels.js", )


admin.site.register(Incident, IncidentAdmin)
admin.site.register(BusinessLine, BusinessLineAdmin)
admin.site.register(BaleCategory)
admin.site.register(Comments)
admin.site.register(LabelGroup)
admin.site.register(Label)
admin.site.register(Label, LabelAdmin)
admin.site.register(IncidentCategory)
admin.site.register(Log)
admin.site.register(Profile)
admin.site.register(IncidentTemplate)
admin.site.register(Attribute)
admin.site.register(ValidAttribute)
admin.site.register(SeverityChoice)
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
Loading