Skip to content

Commit

Permalink
data for timeline (migration needed)
Browse files Browse the repository at this point in the history
  • Loading branch information
ab-smith committed Oct 4, 2024
1 parent 0dc9469 commit 8d3c475
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 2,144 deletions.
22 changes: 22 additions & 0 deletions backend/core/migrations/0030_appliedcontrol_start_date.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Generated by Django 5.1 on 2024-10-04 08:48

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("core", "0029_alter_appliedcontrol_link_alter_evidence_link"),
]

operations = [
migrations.AddField(
model_name="appliedcontrol",
name="start_date",
field=models.DateField(
blank=True,
help_text="Start date (useful for timeline)",
null=True,
verbose_name="Start date",
),
),
]
7 changes: 7 additions & 0 deletions backend/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from django.utils.translation import get_language
from django.utils.translation import gettext_lazy as _
from structlog import get_logger
from django.utils.timezone import now

from iam.models import Folder, FolderMixin, PublishInRootFolderMixin
from library.helpers import (
Expand Down Expand Up @@ -1309,6 +1310,12 @@ class Status(models.TextChoices):
verbose_name=_("Owner"),
related_name="applied_controls",
)
start_date = models.DateField(
blank=True,
null=True,
help_text=_("Start date (useful for timeline)"),
verbose_name=_("Start date"),
)
eta = models.DateField(
blank=True,
null=True,
Expand Down
45 changes: 45 additions & 0 deletions backend/core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
import uuid
import zipfile
from datetime import date, datetime, timedelta
import time
import pytz
from typing import Any, Tuple
from uuid import UUID
import random

import django_filters as df
from django.conf import settings
Expand Down Expand Up @@ -622,6 +625,25 @@ def duplicate(self, request, pk):
return Response({"results": "risk assessment duplicated"})


def convert_date_to_timestamp(date):
"""
Converts a date object (datetime.date) to a Linux timestamp.
It creates a datetime object for the date at midnight and makes it timezone-aware.
"""
if date:
date_as_datetime = datetime.combine(date, datetime.min.time())
aware_datetime = pytz.UTC.localize(date_as_datetime)
return int(time.mktime(aware_datetime.timetuple())) * 1000
return None


def gen_random_html_color():
r = random.randint(150, 255)
g = random.randint(150, 255)
b = random.randint(150, 255)
return "#{:02x}{:02x}{:02x}".format(r, g, b)


class AppliedControlViewSet(BaseModelViewSet):
"""
API endpoint that allows applied controls to be viewed or edited.
Expand Down Expand Up @@ -840,6 +862,29 @@ def get_controls_info(self, request):
}
)

@action(detail=False, methods=["get"])
def get_timeline_info(self, request):
entries = []
colorMap = {}
for ac in AppliedControl.objects.all():
if ac.start_date and ac.eta:
startDate = convert_date_to_timestamp(ac.start_date)
endDate = convert_date_to_timestamp(ac.eta)
entries.append(
{
"startDate": startDate,
"endDate": endDate,
"name": ac.name,
"description": ac.description
if ac.description
else "(no description)",
"domain": ac.folder.name,
}
)
for domain in Folder.objects.all():
colorMap[domain.name] = gen_random_html_color()
return Response({"entries": entries, "colorMap": colorMap})


class PolicyViewSet(AppliedControlViewSet):
model = Policy
Expand Down
1 change: 1 addition & 0 deletions backend/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ pre-commit==3.8.0
django-allauth[saml]==64.2.1
django-allauth==64.2.1
python-magic==0.4.27
pytz==2024.2
6 changes: 5 additions & 1 deletion frontend/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -751,5 +751,9 @@
"ShowAllNodesMessage": "Show all",
"ShowOnlyAssessable": "Only assessable",
"NoPreviewMessage": "No preview available.",
"experimental": "Experimental"
"experimental": "Experimental",
"timeline": "Timeline",
"graph": "Graph",
"startDate": "Start date",
"startDateHelpText": "Start date (useful for timeline)"
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@
bind:cachedValue={formDataCache['evidences']}
label={m.evidences()}
/>
<TextField
type="date"
{form}
field="start_date"
label={m.startDate()}
helpText={m.startDateHelpText()}
cacheLock={cacheLocks['start_date']}
bind:cachedValue={formDataCache['start_date']}
/>
<TextField
type="date"
{form}
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lib/utils/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ export const AppliedControlSchema = baseNamedObject({
status: z.string().optional().default('--'),
evidences: z.string().optional().array().optional(),
eta: z.string().optional().nullable(),
start_date: z.string().optional().nullable(),
expiry_date: z.string().optional().nullable(),
link: z.string().url().optional().or(z.literal('')),
effort: z.string().optional().nullable(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { BASE_API_URL } from '$lib/utils/constants';

import type { PageServerLoad } from './$types';

export const load = (async ({ fetch }) => {
const endpoint = `${BASE_API_URL}/applied-controls/get_timeline_info/`;

const res = await fetch(endpoint);
const data = await res.json();

return { data };
}) satisfies PageServerLoad;
Loading

0 comments on commit 8d3c475

Please sign in to comment.