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

perf: paginate API calls #1332

Merged
merged 129 commits into from
Feb 24, 2025
Merged
Show file tree
Hide file tree
Changes from 112 commits
Commits
Show all changes
129 commits
Select commit Hold shift + click to select a range
89f9012
Switch to limit offset pagination in the backend
nas-tabchiche Jan 7, 2025
3c030c1
Cast PAGIKNATE_BY to int
nas-tabchiche Jan 8, 2025
606d7a9
Backend pagination PoC
nas-tabchiche Jan 8, 2025
d1fb264
Merge branch 'main' into CA-582-handle-backend-pagination
nas-tabchiche Jan 28, 2025
9af35cf
Fix RequirementAssessmentViewSet search fields
nas-tabchiche Jan 28, 2025
b0775bd
Handle search
nas-tabchiche Jan 28, 2025
9824759
handle rowsPerPage
nas-tabchiche Jan 28, 2025
6782d19
Invalidate handler onMount
nas-tabchiche Jan 28, 2025
ac296de
Invalidate handler on seach
nas-tabchiche Jan 28, 2025
93f8671
Return response instead of response.results
nas-tabchiche Jan 28, 2025
cfbcfda
Fix composer regression
nas-tabchiche Jan 28, 2025
2f2de8c
Some tidying
nas-tabchiche Jan 28, 2025
19e2a66
Allow ordering against all model fields by default
nas-tabchiche Jan 28, 2025
5900564
Fix Th sort styling
nas-tabchiche Jan 28, 2025
d41b317
Merge branch 'main' into CA-582-handle-backend-pagination
nas-tabchiche Jan 28, 2025
1358a24
chore: some tidying
nas-tabchiche Jan 28, 2025
09f720b
Merge branch 'main' into CA-582-handle-backend-pagination
nas-tabchiche Jan 29, 2025
f1a4c3d
chore: some tidying
nas-tabchiche Jan 29, 2025
07eab67
Dynamically import either server or client ModelTable component
nas-tabchiche Jan 29, 2025
db7e502
refactor: loaded libraries table
nas-tabchiche Jan 29, 2025
e148c88
Forward slots to client/server ModelTable
nas-tabchiche Jan 29, 2025
4681a18
Remove dead code
nas-tabchiche Jan 29, 2025
9049fc1
Refactor load functions
nas-tabchiche Jan 29, 2025
e26a0ff
Improve libraries routing
nas-tabchiche Jan 29, 2025
337d3a9
Improve slot forwarding on ModelTable
nas-tabchiche Jan 29, 2025
d738d1d
Add null checks
nas-tabchiche Jan 29, 2025
2d7b08f
Use new loaded-libraries routes
nas-tabchiche Jan 29, 2025
bf24bc6
Remove dead code
nas-tabchiche Jan 29, 2025
c5ce0db
Merge branch 'main' into CA-582-handle-backend-pagination
nas-tabchiche Feb 7, 2025
b84f57a
Merge branch 'main' into CA-582-handle-backend-pagination
nas-tabchiche Feb 10, 2025
cdceea5
Get rid of the dynamic import
nas-tabchiche Feb 10, 2025
3f9d9ea
Use URLSearchParams structure
nas-tabchiche Feb 10, 2025
df7e8f3
Fix potential memory leak in riskMatricesPreview function
nas-tabchiche Feb 10, 2025
7d94926
Remove import logic from loaded libraries route
nas-tabchiche Feb 10, 2025
8144aba
Optimize database query and simplify version comparison logic
nas-tabchiche Feb 10, 2025
3f4f6f8
Change HTTP method from GET to POST for library import
nas-tabchiche Feb 10, 2025
5fbac67
Tidy ModelTable component
nas-tabchiche Feb 10, 2025
f01ad2f
Add some error handling around fetch requests
nas-tabchiche Feb 10, 2025
d0b5c9e
Improve accessibility on ModelTable components
nas-tabchiche Feb 10, 2025
090aecc
Fix server-side RowsPerPage component
nas-tabchiche Feb 10, 2025
52b1fbc
Merge branch 'main' into CA-582-handle-backend-pagination
nas-tabchiche Feb 11, 2025
045202d
Add null checks for library objects
nas-tabchiche Feb 11, 2025
27f0c6c
Add /loaded-libraries/available-updates endpoint
nas-tabchiche Feb 11, 2025
96ac4ee
Remove dead code
nas-tabchiche Feb 11, 2025
fccd861
Use new endpoint to get updatable libraries
nas-tabchiche Feb 11, 2025
2aa7854
Adapt new AutocompleteSelect to page serialization
nas-tabchiche Feb 11, 2025
07343d8
Update API tests to use POST for library imports
nas-tabchiche Feb 11, 2025
2869d7d
Fix language display on stored and loaded libraries model tables
nas-tabchiche Feb 11, 2025
928e075
Merge branch 'main' into CA-582-handle-backend-pagination
nas-tabchiche Feb 13, 2025
a43f11d
Properly get row metadata
nas-tabchiche Feb 14, 2025
8e2e92b
Merge branch 'main' into CA-582-handle-backend-pagination
nas-tabchiche Feb 14, 2025
67553b0
Return whole response in third party urlmodels endpoint
nas-tabchiche Feb 14, 2025
2112461
Remove dead code
nas-tabchiche Feb 14, 2025
6529613
Fetch domain filter choices from API
nas-tabchiche Feb 14, 2025
a02032c
Add null check to initialData
nas-tabchiche Feb 14, 2025
851ebc0
Handle array filter values
nas-tabchiche Feb 14, 2025
65c8dd9
Fetch model filter choices from API
nas-tabchiche Feb 14, 2025
0e04b2f
Handle server-side filters
nas-tabchiche Feb 14, 2025
860142d
Delete client-side ModelTable component
nas-tabchiche Feb 14, 2025
cfb352d
Merge branch 'main' into CA-582-handle-backend-pagination
nas-tabchiche Feb 14, 2025
b91f240
Fix filters close query
nas-tabchiche Feb 14, 2025
78f504e
Manage multiple value filters
nas-tabchiche Feb 14, 2025
f886a1a
Merge branch 'main' into CA-582-handle-backend-pagination
eric-intuitem Feb 15, 2025
5b6fc03
Allow multiple options for perimeter folders
nas-tabchiche Feb 15, 2025
7f07929
Merge branch 'main' into CA-582-handle-backend-pagination
nas-tabchiche Feb 17, 2025
a41b04a
Forward static filter choices to frontend
nas-tabchiche Feb 17, 2025
6806cb4
Write FilterKeys type
nas-tabchiche Feb 17, 2025
cb18f93
Merge branch 'main' into CA-582-handle-backend-pagination
nas-tabchiche Feb 17, 2025
68da4c3
Static options fetch PoC
nas-tabchiche Feb 17, 2025
850e2dc
Merge branch 'main' into CA-582-handle-backend-pagination
nas-tabchiche Feb 17, 2025
5756b3b
Remove url parameters from filter endpoints
nas-tabchiche Feb 17, 2025
4ec1de2
Fix incomplete filter visibility logic
nas-tabchiche Feb 17, 2025
81cc975
Add filter fieldContext on AutocompleteSelect
nas-tabchiche Feb 17, 2025
21e5bf4
Always display all filters
nas-tabchiche Feb 18, 2025
a3daacf
Add data-testid for RowCount
nas-tabchiche Feb 18, 2025
1bf7032
Fix table handler fetch endpoints
nas-tabchiche Feb 18, 2025
eb84c43
Always display all filters
nas-tabchiche Feb 18, 2025
a21d6a3
Add risk acceptance state choices endpoint
nas-tabchiche Feb 18, 2025
db8efef
Support some more filters
nas-tabchiche Feb 19, 2025
8358b17
Merge branch 'main' into CA-582-handle-backend-pagination
nas-tabchiche Feb 19, 2025
f7cb3e7
Internationalize singular stakeholder
nas-tabchiche Feb 19, 2025
354cf5d
Remove trailing slash for ebios-rm models' endpointUrl
nas-tabchiche Feb 19, 2025
a80878f
Some tidying
nas-tabchiche Feb 19, 2025
59f6c14
Accept both hyphen and underscores for filter keys
nas-tabchiche Feb 19, 2025
77db33f
Try to use model.endpointUrl before urlmodel
nas-tabchiche Feb 19, 2025
4a8da24
Add custom endpoint for ebios-rm studies
nas-tabchiche Feb 19, 2025
f1af2cc
Add filterset fields to ebios-rm viewsets
nas-tabchiche Feb 19, 2025
7704b98
Add and fix existing filters
nas-tabchiche Feb 19, 2025
f446068
Add finer-grained table handler invalidation to avoid double fetching
nas-tabchiche Feb 19, 2025
8d302bc
refactor: make StoredLibrary content a JSON field
nas-tabchiche Feb 19, 2025
c2e24c7
Merge branch 'refactor/make-storedlibrary-content-json' into CA-582-h…
nas-tabchiche Feb 19, 2025
af6ca51
chore: ruff format
nas-tabchiche Feb 19, 2025
e1f3f9d
Merge branch 'refactor/make-storedlibrary-content-json' into CA-582-h…
nas-tabchiche Feb 19, 2025
02d2827
Adapt stored libraries object type filter to server-side filtering
nas-tabchiche Feb 19, 2025
b2a5665
Clean up table.ts file
nas-tabchiche Feb 19, 2025
d541659
Rename extraProps to props
nas-tabchiche Feb 19, 2025
ff9ff62
Adapt loaded libraries object type filter to server-side filtering
nas-tabchiche Feb 19, 2025
491dfdb
Adapt loaded libraries update available filter to server-side filtering
nas-tabchiche Feb 19, 2025
13d9290
Merge branch 'main' into CA-582-handle-backend-pagination
nas-tabchiche Feb 20, 2025
4e75d50
Merge branch 'main' into CA-582-handle-backend-pagination
ab-smith Feb 20, 2025
d5000a9
Merge branch 'CA-582-handle-backend-pagination' of github.com:intuite…
nas-tabchiche Feb 21, 2025
ed32c14
fix: store risk matrix json definition as a dict, not a str
nas-tabchiche Feb 21, 2025
706b420
Merge branch 'fix/store-matrix-json-definition-as-dict-not-str' into …
nas-tabchiche Feb 21, 2025
916623d
Adapt risk matrix filters to server-side pagination
nas-tabchiche Feb 21, 2025
1e43048
chore: migs
nas-tabchiche Feb 21, 2025
9f73a39
Reove debug log
nas-tabchiche Feb 21, 2025
5052465
Properly initialize data handler if source is provided
nas-tabchiche Feb 21, 2025
6e6fef3
Merge branch 'main' into CA-582-handle-backend-pagination
eric-intuitem Feb 21, 2025
7bd2a34
fix migrations
eric-intuitem Feb 21, 2025
450743f
Update 0055_alter_storedlibrary_content.py
eric-intuitem Feb 22, 2025
59a4cb2
Merge branch 'main' into CA-582-handle-backend-pagination
eric-intuitem Feb 22, 2025
ee3332a
Merge branch 'main' into CA-582-handle-backend-pagination
eric-intuitem Feb 22, 2025
ec91639
try fix functional tests
eric-intuitem Feb 22, 2025
e7b97e0
Merge branch 'main' into CA-582-handle-backend-pagination
nas-tabchiche Feb 24, 2025
4c5eef1
fix: add safeguard to matrix data migration in case json_definition i…
nas-tabchiche Feb 24, 2025
a3dac9d
Merge branch 'refactor/add-safeguards-to-matrix-migration' into CA-58…
nas-tabchiche Feb 24, 2025
688ea92
Properly display loaded library delete button
nas-tabchiche Feb 24, 2025
509d8b9
Pre-populate filter values from url search params
nas-tabchiche Feb 24, 2025
f8689d5
Unwrap library content storage from json.loads
nas-tabchiche Feb 24, 2025
4b9eb0c
Close lingering modals in user route tests
nas-tabchiche Feb 24, 2025
01b272e
Remove framework url filter
nas-tabchiche Feb 24, 2025
10c299d
Move 3s timeout to getByTestId
nas-tabchiche Feb 24, 2025
00db82b
Remove outdated core.filters module
nas-tabchiche Feb 24, 2025
ea9882c
Revert "Remove framework url filter"
nas-tabchiche Feb 24, 2025
3c926c0
Add ref_id search field to library view sets
nas-tabchiche Feb 24, 2025
7290089
Add ref_id column to library model tables
nas-tabchiche Feb 24, 2025
06a4af8
Revert "Move 3s timeout to getByTestId"
nas-tabchiche Feb 24, 2025
2cf7729
Unwrap library content storage from json.loads
nas-tabchiche Feb 24, 2025
eccea8f
Store storedlibrary content as dict not str
nas-tabchiche Feb 24, 2025
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
4 changes: 2 additions & 2 deletions backend/app_tests/api/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ def import_object(client, verbose_name: str, urn: str = None):
url = urn or EndpointTestsUtils.get_object_urn(verbose_name)

# Uses the API endpoint to import an object without authentication
response = client.get(url + "import/")
response = client.post(url + "import/")

# Asserts that the object was imported successfully
assert response.status_code == status.HTTP_401_UNAUTHORIZED, (
Expand Down Expand Up @@ -985,7 +985,7 @@ def import_object(
url = urn or EndpointTestsUtils.get_object_urn(verbose_name)

# Uses the API endpoint to import an object with authentication
response = authenticated_client.get(url + "import/")
response = authenticated_client.post(url + "import/")

# Asserts that the object was imported successfully
if not user_group or user_perm_expected_status == status.HTTP_200_OK:
Expand Down
4 changes: 2 additions & 2 deletions backend/ciso_assistant/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def set_ciso_assistant_url(_, __, event_dict):
MEDIA_ROOT = LOCAL_STORAGE_DIRECTORY
MEDIA_URL = ""

PAGINATE_BY = os.environ.get("PAGINATE_BY", default=5000)
PAGINATE_BY = int(os.environ.get("PAGINATE_BY", default=5000))

# Application definition

Expand Down Expand Up @@ -219,7 +219,7 @@ def set_ciso_assistant_url(_, __, event_dict):
"core.permissions.RBACPermissions",
],
"DEFAULT_FILTER_CLASSES": ["django_filters.rest_framework.DjangoFilterBackend"],
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.LimitOffsetPagination",
"PAGE_SIZE": PAGINATE_BY,
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
"EXCEPTION_HANDLER": "core.helpers.handle",
Expand Down
8 changes: 3 additions & 5 deletions backend/core/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,22 +394,20 @@ def get_parsed_matrices(user: User, risk_assessments: list | None = None):
) = RoleAssignment.get_accessible_object_ids(
Folder.get_root_folder(), user, RiskScenario
)
risk_matrices = list()
if risk_assessments is None:
risk_matrices = (
risk_matrices = list(
RiskScenario.objects.filter(id__in=object_ids_view)
.values_list("risk_assessment__risk_matrix__json_definition", flat=True)
.distinct()
)
else:
risk_matrices = (
risk_matrices = list(
RiskScenario.objects.filter(id__in=object_ids_view)
.filter(risk_assessment__in=risk_assessments)
.values_list("risk_assessment__risk_matrix__json_definition", flat=True)
.distinct()
)
parsed_matrices: list = [json.loads(m) for m in risk_matrices]
return sorted(parsed_matrices, key=lambda m: len(m["risk"]), reverse=True)
return sorted(risk_matrices, key=lambda m: len(m["risk"]), reverse=True)


def get_risk_field(user: User, field: str):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 5.1.4 on 2025-02-21 20:41
# Generated by Django 5.1.4 on 2025-02-21 23:56

from django.db import migrations, models

Expand Down
32 changes: 28 additions & 4 deletions backend/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, RegexValidator, MinValueValidator
from django.db import models, transaction
from django.db.models import Q
from django.db.models import F, Q, OuterRef, Subquery
from django.forms.models import model_to_dict
from django.urls import reverse
from django.utils.html import format_html
Expand Down Expand Up @@ -734,6 +734,30 @@ def reference_count(self) -> int:
+ LoadedLibrary.objects.filter(dependencies=self).distinct().count()
)

@property
def has_update(self) -> bool:
max_version = (
StoredLibrary.objects.filter(urn=self.urn)
.values_list("version", flat=True)
.order_by("-version")
.first()
)
return max_version > self.version if max_version is not None else False

@classmethod
def updatable_libraries(cls):
# Create a subquery to get the highest version in StoredLibrary for the same urn.
latest_version_qs = (
StoredLibrary.objects.filter(urn=OuterRef("urn"))
.order_by("-version")
.values("version")[:1]
)

# Annotate each LoadedLibrary with the latest stored version and filter.
return cls.objects.annotate(
latest_stored_version=Subquery(latest_version_qs)
).filter(latest_stored_version__gt=F("version"))

def delete(self, *args, **kwargs):
if self.reference_count > 0:
raise ValueError(
Expand Down Expand Up @@ -896,10 +920,10 @@ def perimeters(self) -> list:
return Perimeter.objects.filter(riskassessment__risk_matrix=self).distinct()

def parse_json(self) -> dict:
return json.loads(self.json_definition)
return self.json_definition

def parse_json_translated(self) -> dict:
return update_translations_in_object(json.loads(self.json_definition))
return update_translations_in_object(self.json_definition)

@property
def grid(self) -> list:
Expand Down Expand Up @@ -2519,7 +2543,7 @@ def quality_check(self) -> dict:


def risk_scoring(probability, impact, risk_matrix: RiskMatrix) -> int:
fields = json.loads(risk_matrix.json_definition)
fields = risk_matrix.json_definition
risk_index = fields["grid"][probability][impact]
return risk_index
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling to risk_scoring function.

The function should handle potential errors when accessing the grid:

  1. Missing or invalid json_definition
  2. Index out of bounds for probability/impact
 def risk_scoring(probability, impact, risk_matrix: RiskMatrix) -> int:
-    fields = risk_matrix.json_definition
-    risk_index = fields["grid"][probability][impact]
-    return risk_index
+    fields = risk_matrix.json_definition
+    if not fields or "grid" not in fields:
+        raise ValueError("Invalid risk matrix definition")
+    grid = fields["grid"]
+    try:
+        risk_index = grid[probability][impact]
+        return risk_index
+    except IndexError:
+        raise ValueError(f"Invalid probability ({probability}) or impact ({impact}) indices")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def risk_scoring(probability, impact, risk_matrix: RiskMatrix) -> int:
fields = json.loads(risk_matrix.json_definition)
fields = risk_matrix.json_definition
risk_index = fields["grid"][probability][impact]
return risk_index
def risk_scoring(probability, impact, risk_matrix: RiskMatrix) -> int:
fields = risk_matrix.json_definition
if not fields or "grid" not in fields:
raise ValueError("Invalid risk matrix definition")
grid = fields["grid"]
try:
risk_index = grid[probability][impact]
return risk_index
except IndexError:
raise ValueError(f"Invalid probability ({probability}) or impact ({impact}) indices")


Expand Down
Loading
Loading