From a51da8fc111d2b2dad6dcd48e455f6a6804e1c54 Mon Sep 17 00:00:00 2001 From: JadeWibbels Date: Wed, 22 Jan 2025 18:06:09 -0700 Subject: [PATCH] HJ-338 added sorting for system.privacy_declarations and a test to verify (#5683) Co-authored-by: Jade Wibbels --- CHANGELOG.md | 1 + src/fides/api/models/sql_models.py | 1 + tests/ctl/core/test_api.py | 24 ++++++++++ tests/ctl/models/test_sql_models.py | 34 +++++++++++++++ tests/ops/integration_tests/test_sql_task.py | 46 +++++++++++--------- 5 files changed, 85 insertions(+), 21 deletions(-) create mode 100644 tests/ctl/models/test_sql_models.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 798966327d..1aef227944 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ Changes can also be flagged with a GitHub label for tracking purposes. The URL o ### Changed - Updated UI colors to new brand. Update logo, homepage cards. [#5668](https://github.com/ethyca/fides/pull/5668) +- The privacy declarations for a system are now sorted alphabetically by name. [#5683](https://github.com/ethyca/fides/pull/5683) ### Developer Experience - Migrated radio buttons and groups to Ant Design [#5681](https://github.com/ethyca/fides/pull/5681) diff --git a/src/fides/api/models/sql_models.py b/src/fides/api/models/sql_models.py index c89e90c526..ff45fd8b7a 100644 --- a/src/fides/api/models/sql_models.py +++ b/src/fides/api/models/sql_models.py @@ -416,6 +416,7 @@ class System(Base, FidesBase): cascade="all, delete", back_populates="system", lazy="selectin", + order_by="PrivacyDeclaration.name", ) data_stewards = relationship( diff --git a/tests/ctl/core/test_api.py b/tests/ctl/core/test_api.py index c6a61b8730..321bd95ac2 100644 --- a/tests/ctl/core/test_api.py +++ b/tests/ctl/core/test_api.py @@ -1263,6 +1263,30 @@ def test_data_stewards_included_in_response( assert "first_name" in steward assert "last_name" in steward + def test_system_privacy_declarations_are_sorted(self, test_config, system, db): + """Test system Privacy Declarations are returned in alphabetical order by name.""" + data = { + "data_use": "essential", + "name": "Another Declaration Name", + "system_id": system.id, + "data_subjects": [], + "data_categories": [], + } + new_pd = PrivacyDeclaration.create(db, data=data) + + result = _api.get( + url=test_config.cli.server_url, + headers=test_config.user.auth_header, + resource_type="system", + resource_id=system.fides_key, + ) + assert result.status_code == 200 + + privacy_declarations = result.json()["privacy_declarations"] + assert len(privacy_declarations) == 2 + assert privacy_declarations[0]["name"] == "Another Declaration Name" + assert privacy_declarations[1]["name"] == "Collect data for marketing" + @pytest.mark.unit class TestSystemList: diff --git a/tests/ctl/models/test_sql_models.py b/tests/ctl/models/test_sql_models.py new file mode 100644 index 0000000000..707c5f51f4 --- /dev/null +++ b/tests/ctl/models/test_sql_models.py @@ -0,0 +1,34 @@ +from fides.api.db.system import get_system +from fides.api.models.sql_models import PrivacyDeclaration + + +def test_system_privacy_declarations_in_alphabetical_order(db, system): + """ + Ensure that the system privacy declarations are in alphabetical order by name + """ + # Add more privacy declarations to the system + new_privacy_declarations = [ + { + "data_use": "marketing.advertising.profiling", + "name": "Declaration Name", + "system_id": system.id, + }, + { + "data_use": "essential", + "name": "Another Declaration Name", + "system_id": system.id, + }, + ] + for data in new_privacy_declarations: + PrivacyDeclaration.create(db=db, data=data) + db.commit() + + db.refresh(system) + updated_system = get_system(db, system.fides_key) + + privacy_declarations = updated_system.privacy_declarations + sorted_privacy_declarations = sorted(privacy_declarations, key=lambda x: x.name) + + assert ( + privacy_declarations == sorted_privacy_declarations + ), "Privacy declarations are not in alphabetical order by name" diff --git a/tests/ops/integration_tests/test_sql_task.py b/tests/ops/integration_tests/test_sql_task.py index bbac30df82..e0ce349d8f 100644 --- a/tests/ops/integration_tests/test_sql_task.py +++ b/tests/ops/integration_tests/test_sql_task.py @@ -933,27 +933,31 @@ async def test_retry_access_request( # All four nodes directly downstream of the root node attempt to process, # and nothing further processes downstream - assert [ - ( - get_collection_identifier(log), - log.status.value, - ) - for log in execution_logs.order_by(ExecutionLog.created_at) - ] == [ - ("Dataset traversal", "complete"), - ("postgres_example_test_dataset:customer", "in_processing"), - ("postgres_example_test_dataset:customer", "retrying"), - ("postgres_example_test_dataset:customer", "error"), - ("postgres_example_test_dataset:employee", "in_processing"), - ("postgres_example_test_dataset:employee", "retrying"), - ("postgres_example_test_dataset:employee", "error"), - ("postgres_example_test_dataset:report", "in_processing"), - ("postgres_example_test_dataset:report", "retrying"), - ("postgres_example_test_dataset:report", "error"), - ("postgres_example_test_dataset:visit", "in_processing"), - ("postgres_example_test_dataset:visit", "retrying"), - ("postgres_example_test_dataset:visit", "error"), - ] + assert set( + [ + ( + get_collection_identifier(log), + log.status.value, + ) + for log in execution_logs.order_by(ExecutionLog.created_at) + ] + ) == set( + [ + ("Dataset traversal", "complete"), + ("postgres_example_test_dataset:customer", "in_processing"), + ("postgres_example_test_dataset:customer", "retrying"), + ("postgres_example_test_dataset:customer", "error"), + ("postgres_example_test_dataset:employee", "in_processing"), + ("postgres_example_test_dataset:employee", "retrying"), + ("postgres_example_test_dataset:employee", "error"), + ("postgres_example_test_dataset:report", "in_processing"), + ("postgres_example_test_dataset:report", "retrying"), + ("postgres_example_test_dataset:report", "error"), + ("postgres_example_test_dataset:visit", "in_processing"), + ("postgres_example_test_dataset:visit", "retrying"), + ("postgres_example_test_dataset:visit", "error"), + ] + ) # Downstream request tasks were marked as error assert [rt.status.value for rt in privacy_request.access_tasks] == [ "complete",