diff --git a/src/fides/api/models/detection_discovery.py b/src/fides/api/models/detection_discovery.py index bb36c16ac2..1a6de437c8 100644 --- a/src/fides/api/models/detection_discovery.py +++ b/src/fides/api/models/detection_discovery.py @@ -13,6 +13,7 @@ from fides.api.db.base_class import Base, FidesBase from fides.api.models.connectionconfig import ConnectionConfig +from fides.api.models.sql_models import System # class MonitorExecution(BaseModel): # id: str @@ -234,11 +235,29 @@ class StagedResource(Base): urn = Column(String, index=True, unique=True, nullable=False) resource_type = Column(String, index=True, nullable=True) description = Column(String, nullable=True) - monitor_config_id = Column(String, nullable=True) # just a "soft" pointer, for now + monitor_config_id = Column( + String, + index=True, # indexed because we frequently need to slice by monitor config ID + nullable=True, + ) # just a "soft" pointer, for now TODO: make this a FK + + system_id = Column( + String, + ForeignKey(System.id_field_path), + nullable=True, + index=True, + ) + system = relationship(System) + vendor_id = Column( + String, + nullable=True, + index=True, # indexed because we frequently need to slice by vendor ID + ) # the Compass vendor ID associated with the StagedResource + source_modified = Column( DateTime(timezone=True), nullable=True, - ) # when the table was modified in the datasource + ) # when the resource was modified in the datasource classifications = Column( ARRAY(JSONB), nullable=False, diff --git a/tests/ops/models/test_detection_discovery.py b/tests/ops/models/test_detection_discovery.py index 03164d0e5b..ab8c806fc2 100644 --- a/tests/ops/models/test_detection_discovery.py +++ b/tests/ops/models/test_detection_discovery.py @@ -186,6 +186,95 @@ def test_staged_resource_helpers(self, db: Session, create_staged_resource): } +class TestStagedResourceModelWebMonitorResults: + """Tests for the StagedResource model related to web monitor result applications""" + + @pytest.fixture + def create_web_monitor_staged_resource(self, db: Session, system): + urn = "my_web_monitor_1.GET.td.doubleclick.net.https://td.doubleclick.net/td/ga/rul" + resource = StagedResource.create( + db=db, + # the data below is representative of a web monitor result staged resource + data={ + "urn": urn, + "user_assigned_data_categories": ["user.contact.email"], + "name": "rul", + "resource_type": "Browser Request", + "monitor_config_id": "my_web_monitor_1", + "diff_status": DiffStatus.ADDITION.value, + "system_id": system.id, + "vendor_id": "sample_compass_vendor_id", + "meta": { + "domain": "td.doubleclick.net", + "method": "GET", + "parent": "https://www.googletagmanager.com/gtag/js?id=G-B356CF15GS", + "cookies": [ + "test_cookie=CheckForPermission; expires=Fri, 13-Dec-2024 15:25:18 GMT; path=/; domain=.doubleclick.net; Secure; SameSite=none" + ], + "base_url": "https://td.doubleclick.net/td/ga/rul", + "data_uses": [], + "locations": ["USA"], + "mime_type": "text/html", + "parent_domain": "www.googletagmanager.com", + }, + }, + ) + yield resource + db.delete(resource) + + def test_create_staged_resource( + self, db: Session, system, create_web_monitor_staged_resource + ) -> None: + """ + Creation fixture creates the resource, this tests that it was created successfully + and that we can access its attributes as expected + """ + saved_resource: StagedResource = StagedResource.get_urn( + db, create_web_monitor_staged_resource.urn + ) + assert saved_resource.system.name == system.name + assert saved_resource.meta == { + "domain": "td.doubleclick.net", + "method": "GET", + "parent": "https://www.googletagmanager.com/gtag/js?id=G-B356CF15GS", + "cookies": [ + "test_cookie=CheckForPermission; expires=Fri, 13-Dec-2024 15:25:18 GMT; path=/; domain=.doubleclick.net; Secure; SameSite=none" + ], + "base_url": "https://td.doubleclick.net/td/ga/rul", + "data_uses": [], + "locations": ["USA"], + "mime_type": "text/html", + "parent_domain": "www.googletagmanager.com", + } + assert saved_resource.diff_status == DiffStatus.ADDITION.value + assert saved_resource.vendor_id == "sample_compass_vendor_id" + + def test_update_staged_resource( + self, + db: Session, + create_web_monitor_staged_resource, + system, + system_hidden, + ) -> None: + """ + Tests that we can update a staged resource, specifically its web-monitor related properties + """ + saved_resource: StagedResource = StagedResource.get_urn( + db, create_web_monitor_staged_resource.urn + ) + + # check system initially + assert saved_resource.system.name == system.name + + saved_resource.system = system_hidden + # needed to ensure array updates are persisted to the db + flag_modified(saved_resource, "system") + + saved_resource.save(db) + updated_resource = StagedResource.get_urn(db, saved_resource.urn) + assert updated_resource.system.name == system_hidden.name + + SAMPLE_START_DATE = datetime(2024, 5, 20, 0, 42, 5, 17137, tzinfo=timezone.utc)