Skip to content

Commit

Permalink
Show systems without privacy declarations on data map (#1603)
Browse files Browse the repository at this point in the history
* add failing test for system sans privacy declaration

* handle systems without privacy declarations

* changelog

* [skip ci] Update tests/ctl/core/test_export.py

Co-authored-by: Allison King <allisonjuliaking@gmail.com>

* improve naming, add comment for final column n/a

Co-authored-by: Allison King <allisonjuliaking@gmail.com>
  • Loading branch information
SteveDMurphy and allisonking committed Nov 1, 2022
1 parent c31ceec commit 5657039
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 40 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ The types of changes are:
* `Fixed` for any bug fixes.
* `Security` in case of vulnerabilities.

## [Unreleased](https://github.com/ethyca/fides/compare/1.9.5...main)
## [Unreleased](https://github.com/ethyca/fides/compare/1.9.6...main)

## [1.9.6](https://github.com/ethyca/fides/compare/1.9.5...1.9.6)

### Fixed

* Include systems without a privacy declaration on data map [#1603](https://github.com/ethyca/fides/pull/1603)

## [1.9.5](https://github.com/ethyca/fides/compare/1.9.4...1.9.5)

Expand Down
106 changes: 67 additions & 39 deletions src/fidesctl/ctl/core/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
)
from fidesctl.ctl.core.utils import echo_green, get_all_level_fields

EMPTY_COLUMN_PLACEHOLDER = "N/A"


def generate_dataset_records(
server_dataset_list: List,
Expand Down Expand Up @@ -174,45 +176,71 @@ def generate_system_records(
system.data_protection_impact_assessment.dict()
)
)
for declaration in system.privacy_declarations:
data_use = formatted_data_uses[declaration.data_use]
data_categories = declaration.data_categories or []
data_subjects = [
formatted_data_subjects[data_subject_fides_key]
for data_subject_fides_key in declaration.data_subjects
if system.privacy_declarations:
for declaration in system.privacy_declarations:
data_use = formatted_data_uses[declaration.data_use]
data_categories = declaration.data_categories or []
data_subjects = [
formatted_data_subjects[data_subject_fides_key]
for data_subject_fides_key in declaration.data_subjects
]
dataset_references = declaration.dataset_references or [
EMPTY_COLUMN_PLACEHOLDER
]
cartesian_product_of_declaration = [
(
system.fides_key,
system.name,
system.description,
system.data_responsibility_title,
system.administrating_department,
third_country_list,
system_dependencies,
declaration.name,
category,
data_use["name"],
data_use["legal_basis"],
data_use["special_category"],
data_use["recipients"],
data_use["legitimate_interest"],
data_use["legitimate_interest_impact_assessment"],
subject["name"],
subject["rights_available"],
subject["automated_decisions_or_profiling"],
declaration.data_qualifier,
data_protection_impact_assessment["is_required"],
data_protection_impact_assessment["progress"],
data_protection_impact_assessment["link"],
dataset_reference,
)
for category in data_categories
for subject in data_subjects
for dataset_reference in dataset_references
]
output_list += cartesian_product_of_declaration
else:
system_row = [
system.fides_key,
system.name,
system.description,
system.data_responsibility_title,
system.administrating_department,
third_country_list,
system_dependencies,
data_protection_impact_assessment["is_required"],
data_protection_impact_assessment["progress"],
data_protection_impact_assessment["link"],
]
dataset_references = declaration.dataset_references or ["N/A"]
cartesian_product_of_declaration = [
(
system.fides_key,
system.name,
system.description,
system.data_responsibility_title,
system.administrating_department,
third_country_list,
system_dependencies,
declaration.name,
category,
data_use["name"],
data_use["legal_basis"],
data_use["special_category"],
data_use["recipients"],
data_use["legitimate_interest"],
data_use["legitimate_interest_impact_assessment"],
subject["name"],
subject["rights_available"],
subject["automated_decisions_or_profiling"],
declaration.data_qualifier,
data_protection_impact_assessment["is_required"],
data_protection_impact_assessment["progress"],
data_protection_impact_assessment["link"],
dataset_reference,
num_privacy_declaration_fields = 12
privacy_declaration_start_index = 6
for i in range(num_privacy_declaration_fields):
system_row.insert(
i + privacy_declaration_start_index, EMPTY_COLUMN_PLACEHOLDER
)
for category in data_categories
for subject in data_subjects
for dataset_reference in dataset_references
]
output_list += cartesian_product_of_declaration
system_row.append(EMPTY_COLUMN_PLACEHOLDER)

# also add n/a for the dataset reference
output_list += [tuple(system_row)]

return output_list

Expand Down Expand Up @@ -376,7 +404,7 @@ def build_joined_dataframe(

# merge systems and datasets
joined_df = systems_df.merge(datasets_df, how="left", on=["dataset.fides_key"])
joined_df.fillna("N/A", inplace=True)
joined_df.fillna(EMPTY_COLUMN_PLACEHOLDER, inplace=True)
## create a set of third_country attrs to combine as a single entity
joined_df["third_country_combined"] = [
convert_tuple_to_string(i)
Expand Down Expand Up @@ -408,7 +436,7 @@ def build_joined_dataframe(
> 1
].drop_duplicates()

delete_df["dataset.name"] = "N/A"
delete_df["dataset.name"] = EMPTY_COLUMN_PLACEHOLDER

joined_df = (
pd.merge(joined_df, delete_df, indicator=True, how="outer")
Expand Down
14 changes: 14 additions & 0 deletions tests/ctl/core/test_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,20 @@ def test_system_records_to_export(
assert len(output_list) == 3


@pytest.mark.unit
def test_system_records_to_export_sans_privacy_declaration(
test_sample_system_taxonomy: Generator, test_config: FidesConfig
) -> None:
"""
Asserts that unique records for systems without a privacy declaration
are returned properly (including the header row)
"""
test_sample_system_taxonomy["system"][0].privacy_declarations = []
output_list = export.generate_system_records(test_sample_system_taxonomy)
print(output_list)
assert len(output_list) == 2


@pytest.mark.unit
def test_dataset_records_to_export(test_sample_dataset_taxonomy: Generator) -> None:
"""
Expand Down

0 comments on commit 5657039

Please sign in to comment.