Skip to content

Commit

Permalink
Merge branch 'main' into action-trigger-on-itself
Browse files Browse the repository at this point in the history
  • Loading branch information
dekkers authored Oct 15, 2024
2 parents 6150a7b + c53f98d commit 688cca9
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 19 deletions.
6 changes: 3 additions & 3 deletions mula/scheduler/storage/filters/casting.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ def cast_expression(expression: BinaryExpression, filter_: Filter) -> BinaryExpr
# if the value can be decoded.
try:
decoded_value = json.loads(filter_.value)
if isinstance(decoded_value, dict):
# If it's a JSON object, return the expression as is. We don't
# need to cast it.
# If the string is a JSON object, return the expression as is.
# We don't need to cast it.
if isinstance(decoded_value, dict | list):
return expression
expression = expression.astext
except json.JSONDecodeError:
Expand Down
28 changes: 28 additions & 0 deletions mula/tests/integration/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,34 @@ def test_pop_queue_filters_nested(self):
self.assertEqual(second_item_id, response.json().get("id"))
self.assertEqual(0, self.scheduler.queue.qsize())

def test_pop_queue_filters_nested_contained_by(self):
# Add one task to the queue
first_item = create_task_in(1, data=functions.TestModel(id="123", name="test", categories=["foo", "bar"]))
response = self.client.post(f"/queues/{self.scheduler.scheduler_id}/push", data=first_item)
self.assertEqual(response.status_code, 201)
self.assertEqual(1, self.scheduler.queue.qsize())

# Add second item to the queue
second_item = create_task_in(2, data=functions.TestModel(id="456", name="test", categories=["baz", "bat"]))
response = self.client.post(f"/queues/{self.scheduler.scheduler_id}/push", data=second_item)
second_item_id = response.json().get("id")
self.assertEqual(response.status_code, 201)
self.assertEqual(2, self.scheduler.queue.qsize())

# Test contained by
response = self.client.post(
f"/queues/{self.scheduler.scheduler_id}/pop",
json={
"filters": [
{"column": "data", "operator": "<@", "field": "categories", "value": json.dumps(["baz", "bat"])}
]
},
)

self.assertEqual(200, response.status_code)
self.assertEqual(second_item_id, response.json().get("id"))
self.assertEqual(1, self.scheduler.queue.qsize())

def test_pop_empty(self):
"""When queue is empty it should return an empty response"""
response = self.client.post(f"/queues/{self.scheduler.scheduler_id}/pop")
Expand Down
38 changes: 32 additions & 6 deletions mula/tests/unit/test_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,31 @@ def setUp(self):
age=25,
height=1.8,
is_active=True,
data={"foo": "bar", "score": 15, "nested": {"bar": "baz"}, "list": ["foo", "bar"]},
data={"foo": "bar", "score": 15, "nested": {"bar": "baz"}, "list": ["ipv4", "network/local"]},
),
TestModel(
name="Bob",
age=30,
height=1.7,
is_active=False,
data={"foo": "baz", "score": 25, "nested": {"bar": "baz"}, "list": ["bar", "baz"]},
data={
"foo": "baz",
"score": 25,
"nested": {"bar": "baz"},
"list": ["ipv4", "ipv6", "network/local"],
},
),
TestModel(
name="Charlie",
age=28,
height=1.6,
is_active=True,
data={"foo": "bar", "score": 35, "nested": {"bar": "baz"}, "list": ["foo", "bar"]},
data={
"foo": "bar",
"score": 35,
"nested": {"bar": "baz"},
"list": ["ipv4", "ipv6", "network/internet"],
},
),
]
)
Expand Down Expand Up @@ -705,9 +715,25 @@ def test_apply_filter_jsonb_contains(self):
self.assertEqual(results[0].name, "Alice")
self.assertEqual(results[1].name, "Charlie")

def test_apply_filter_jsonb_in_list(self):
def test_apply_filter_jsonb_contains_list(self):
filter_request = FilterRequest(
filters=[Filter(column="data", operator="@>", value=json.dumps({"list": ["foo"]}))]
filters=[Filter(column="data", field="list", operator="@>", value=json.dumps(["ipv4"]))]
)

query = session.query(TestModel)
filtered_query = apply_filter(TestModel, query, filter_request)

results = filtered_query.order_by(TestModel.name).all()
self.assertEqual(len(results), 3)
self.assertEqual(results[0].name, "Alice")
self.assertEqual(results[1].name, "Bob")
self.assertEqual(results[2].name, "Charlie")

def test_apply_filter_jsonb_contained_by_list(self):
filter_request = FilterRequest(
filters=[
Filter(column="data", field="list", operator="<@", value=json.dumps(["ipv4", "ipv6", "network/local"]))
]
)

query = session.query(TestModel)
Expand All @@ -716,4 +742,4 @@ def test_apply_filter_jsonb_in_list(self):
results = filtered_query.order_by(TestModel.name).all()
self.assertEqual(len(results), 2)
self.assertEqual(results[0].name, "Alice")
self.assertEqual(results[1].name, "Charlie")
self.assertEqual(results[1].name, "Bob")
13 changes: 12 additions & 1 deletion rocky/reports/report_types/findings_report/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,18 @@ class FindingsReport(Report):
id = "findings-report"
name = _("Findings Report")
description = _("Shows all the finding types and their occurrences.")
plugins: ReportPlugins = {"required": set(), "optional": set()}
plugins: ReportPlugins = {
"required": {
"dns-records",
"nmap",
"nmap-udp",
"webpage-analysis",
"ssl-version",
"ssl-certificates",
"testssl-sh-ciphers",
},
"optional": {"snyk", "service_banner", "shodan", "leakix"},
}
input_ooi_types = ALL_TYPES
template_path = "findings_report/report.html"
label_style = "3-light"
Expand Down
9 changes: 4 additions & 5 deletions rocky/reports/report_types/vulnerability_report/report.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
{% load i18n %}
{% load report_extra %}

{% if data %}
{% if data|sum_findings == 0 %}
<p>{% translate "No vulnerabilities have been found on this system." %}</p>
{% else %}
{% for ip, vulnerability_data in data.items %}
{% if vulnerability_data.summary.total_findings > 0 %}
{% if show_heading %}
Expand Down Expand Up @@ -91,10 +94,6 @@ <h3>{% translate "Host:" %} {{ ip|human_readable }} {{ vulnerability_data.hostna
</tbody>
</table>
</div>
{% else %}
{% if data|length == 1 %}
<p>{% translate "No vulnerabilities have been found on this system." %}</p>
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
7 changes: 7 additions & 0 deletions rocky/reports/templatetags/report_extra.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Any

from django import template

from reports.report_types.helpers import get_report_by_id
Expand All @@ -10,6 +12,11 @@ def sum_attribute(checks, attribute):
return sum(int(check[attribute]) for check in checks)


@register.filter
def sum_findings(data: dict[str, Any]) -> int:
return sum(int(ip["summary"]["total_findings"]) for ip in data.values())


@register.filter
def get_report_type_name(report_type_id: str):
return get_report_by_id(report_type_id).name
Expand Down
8 changes: 4 additions & 4 deletions rocky/rocky/locale/django.pot
Original file line number Diff line number Diff line change
Expand Up @@ -3568,6 +3568,10 @@ msgid ""
"protocols."
msgstr ""

#: reports/report_types/vulnerability_report/report.html
msgid "No vulnerabilities have been found on this system."
msgstr ""

#: reports/report_types/vulnerability_report/report.html
msgid ""
"The Vulnerability Report provides an overview of all identified CVE "
Expand All @@ -3580,10 +3584,6 @@ msgstr ""
msgid "Advice"
msgstr ""

#: reports/report_types/vulnerability_report/report.html
msgid "No vulnerabilities have been found on this system."
msgstr ""

#: reports/report_types/vulnerability_report/report.py
msgid "Vulnerability Report"
msgstr ""
Expand Down

0 comments on commit 688cca9

Please sign in to comment.