ethyca-fides 2.66.1rc0__py2.py3-none-any.whl → 2.66.2b1__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ethyca-fides might be problematic. Click here for more details.
- {ethyca_fides-2.66.1rc0.dist-info → ethyca_fides-2.66.2b1.dist-info}/METADATA +1 -1
- {ethyca_fides-2.66.1rc0.dist-info → ethyca_fides-2.66.2b1.dist-info}/RECORD +264 -254
- fides/_version.py +3 -3
- fides/api/alembic/migrations/versions/7e9a2b52f498_adding_masking_secrets.py +60 -0
- fides/api/alembic/migrations/versions/a7065df4dcf1_add_finalized_fields_to_privacy_request.py +65 -0
- fides/api/alembic/migrations/versions/d0031087eacb_create_manualtaskconditionaldependency_.py +106 -0
- fides/api/api/v1/endpoints/dataset_config_endpoints.py +13 -5
- fides/api/api/v1/endpoints/drp_endpoints.py +7 -1
- fides/api/api/v1/endpoints/privacy_request_endpoints.py +44 -1
- fides/api/api/v1/endpoints/user_endpoints.py +83 -7
- fides/api/app_setup.py +3 -2
- fides/api/common_exceptions.py +4 -0
- fides/api/db/base.py +1 -0
- fides/api/db/database.py +1 -1
- fides/api/graph/execution.py +30 -0
- fides/api/models/manual_task/__init__.py +2 -0
- fides/api/models/manual_task/conditional_dependency.py +144 -0
- fides/api/models/{manual_task.py → manual_task/manual_task.py} +10 -0
- fides/api/models/masking_secret.py +72 -0
- fides/api/models/policy.py +23 -0
- fides/api/models/privacy_request/execution_log.py +1 -0
- fides/api/models/privacy_request/privacy_request.py +31 -13
- fides/api/oauth/roles.py +2 -0
- fides/api/schemas/application_config.py +11 -1
- fides/api/schemas/masking/masking_secrets.py +1 -1
- fides/api/schemas/policy.py +1 -0
- fides/api/schemas/privacy_request.py +5 -0
- fides/api/service/connectors/base_connector.py +1 -0
- fides/api/service/connectors/bigquery_connector.py +67 -19
- fides/api/service/connectors/dynamodb_connector.py +2 -1
- fides/api/service/connectors/fides_connector.py +1 -0
- fides/api/service/connectors/http_connector.py +1 -0
- fides/api/service/connectors/manual_task_connector.py +1 -0
- fides/api/service/connectors/manual_webhook_connector.py +2 -1
- fides/api/service/connectors/mongodb_connector.py +1 -0
- fides/api/service/connectors/okta_connector.py +1 -0
- fides/api/service/connectors/query_configs/bigquery_query_config.py +91 -32
- fides/api/service/connectors/rds_mysql_connector.py +1 -0
- fides/api/service/connectors/rds_postgres_connector.py +1 -0
- fides/api/service/connectors/s3_connector.py +1 -0
- fides/api/service/connectors/saas_connector.py +1 -0
- fides/api/service/connectors/scylla_connector.py +1 -0
- fides/api/service/connectors/sql_connector.py +36 -4
- fides/api/service/connectors/website_connector.py +1 -0
- fides/api/service/privacy_request/request_runner_service.py +142 -53
- fides/api/service/privacy_request/request_service.py +1 -22
- fides/api/task/conditional_dependencies/__init__.py +0 -0
- fides/api/task/conditional_dependencies/evaluator.py +109 -0
- fides/api/task/conditional_dependencies/schemas.py +54 -0
- fides/api/task/deprecated_graph_task.py +24 -6
- fides/api/task/execute_request_tasks.py +88 -11
- fides/api/task/graph_task.py +38 -3
- fides/api/task/manual/manual_task_graph_task.py +1 -0
- fides/api/util/cache.py +5 -0
- fides/api/util/encryption/secrets_util.py +48 -18
- fides/common/api/scope_registry.py +3 -0
- fides/common/api/v1/urn_registry.py +1 -1
- fides/config/execution_settings.py +4 -0
- fides/config/utils.py +1 -0
- fides/service/privacy_request/privacy_request_service.py +6 -1
- fides/ui-build/static/admin/404.html +1 -1
- fides/ui-build/static/admin/_next/static/CQD5hIjm-4lH18YYESYuD/_buildManifest.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/1817-6f35f58cd08b04ae.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{203-5a663f465ba26bb4.js → 203-4e777c324a01dbec.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/431-ade3e312fac3430b.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/6780-4b687168dd8daa84.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/8237-55049f8f5fd5e058.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/{_app-39ccb07327c2c5d5.js → _app-be7889cec5a0f5cd.js} +56 -56
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-71579a199158952e.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]-7e63ac744c45f6da.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/{integrations-e2d5d7e2a5265e68.js → integrations-f10a7dcf7541c865.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/{table-migration-69ad86b7a8a9a115.js → table-migration-05616e2ae20ff4f8.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-1caa552a8f11f2f2.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-7498d1d5974a78b0.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-2d3a2d967767a131.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-6a9068df48bdee05.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/[id]-fe58cebba358119d.js +1 -0
- fides/ui-build/static/admin/_next/static/css/{5bfb2473e5701527.css → 23cf870196941c9a.css} +1 -1
- fides/ui-build/static/admin/_next/static/css/b81194f2c3930152.css +1 -0
- fides/ui-build/static/admin/add-systems/manual.html +1 -1
- fides/ui-build/static/admin/add-systems/multiple.html +1 -1
- fides/ui-build/static/admin/add-systems.html +1 -1
- fides/ui-build/static/admin/consent/configure/add-vendors.html +1 -1
- fides/ui-build/static/admin/consent/configure.html +1 -1
- fides/ui-build/static/admin/consent/privacy-experience/[id].html +1 -1
- fides/ui-build/static/admin/consent/privacy-experience/new.html +1 -1
- fides/ui-build/static/admin/consent/privacy-experience.html +1 -1
- fides/ui-build/static/admin/consent/privacy-notices/[id].html +1 -1
- fides/ui-build/static/admin/consent/privacy-notices/new.html +1 -1
- fides/ui-build/static/admin/consent/privacy-notices.html +1 -1
- fides/ui-build/static/admin/consent/properties.html +1 -1
- fides/ui-build/static/admin/consent/reporting.html +1 -1
- fides/ui-build/static/admin/consent.html +1 -1
- fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn].html +1 -1
- fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn].html +1 -1
- fides/ui-build/static/admin/data-catalog/[systemId]/projects.html +1 -1
- fides/ui-build/static/admin/data-catalog/[systemId]/resources/[resourceUrn].html +1 -1
- fides/ui-build/static/admin/data-catalog/[systemId]/resources.html +1 -1
- fides/ui-build/static/admin/data-catalog.html +1 -1
- fides/ui-build/static/admin/data-discovery/action-center/[monitorId]/[systemId].html +1 -1
- fides/ui-build/static/admin/data-discovery/action-center/[monitorId].html +1 -1
- fides/ui-build/static/admin/data-discovery/action-center.html +1 -1
- fides/ui-build/static/admin/data-discovery/activity.html +1 -1
- fides/ui-build/static/admin/data-discovery/detection/[resourceUrn].html +1 -1
- fides/ui-build/static/admin/data-discovery/detection.html +1 -1
- fides/ui-build/static/admin/data-discovery/discovery/[resourceUrn].html +1 -1
- fides/ui-build/static/admin/data-discovery/discovery.html +1 -1
- fides/ui-build/static/admin/datamap.html +1 -1
- fides/ui-build/static/admin/dataset/[datasetId]/[collectionName]/[...subfieldNames].html +1 -1
- fides/ui-build/static/admin/dataset/[datasetId]/[collectionName].html +1 -1
- fides/ui-build/static/admin/dataset/[datasetId].html +1 -1
- fides/ui-build/static/admin/dataset/new.html +1 -1
- fides/ui-build/static/admin/dataset.html +1 -1
- fides/ui-build/static/admin/datastore-connection/[id].html +1 -1
- fides/ui-build/static/admin/datastore-connection/new.html +1 -1
- fides/ui-build/static/admin/datastore-connection.html +1 -1
- fides/ui-build/static/admin/index.html +1 -1
- fides/ui-build/static/admin/integrations/[id].html +1 -1
- fides/ui-build/static/admin/integrations.html +1 -1
- fides/ui-build/static/admin/lib/fides-ext-gpp.js +1 -1
- fides/ui-build/static/admin/lib/fides-headless.js +1 -1
- fides/ui-build/static/admin/lib/fides-preview.js +1 -1
- fides/ui-build/static/admin/lib/fides-tcf.js +3 -3
- fides/ui-build/static/admin/lib/fides.js +3 -3
- fides/ui-build/static/admin/login/[provider].html +1 -1
- fides/ui-build/static/admin/login.html +1 -1
- fides/ui-build/static/admin/messaging/[id].html +1 -1
- fides/ui-build/static/admin/messaging/add-template.html +1 -1
- fides/ui-build/static/admin/messaging.html +1 -1
- fides/ui-build/static/admin/poc/ant-components.html +1 -1
- fides/ui-build/static/admin/poc/form-experiments/AntForm.html +1 -1
- fides/ui-build/static/admin/poc/form-experiments/FormikAntFormItem.html +1 -1
- fides/ui-build/static/admin/poc/form-experiments/FormikControlled.html +1 -1
- fides/ui-build/static/admin/poc/form-experiments/FormikField.html +1 -1
- fides/ui-build/static/admin/poc/form-experiments/FormikSpreadField.html +1 -1
- fides/ui-build/static/admin/poc/forms.html +1 -1
- fides/ui-build/static/admin/poc/table-migration.html +1 -1
- fides/ui-build/static/admin/privacy-requests/[id].html +1 -1
- fides/ui-build/static/admin/privacy-requests/configure/messaging.html +1 -1
- fides/ui-build/static/admin/privacy-requests/configure/storage.html +1 -1
- fides/ui-build/static/admin/privacy-requests/configure.html +1 -1
- fides/ui-build/static/admin/privacy-requests.html +1 -1
- fides/ui-build/static/admin/properties/[id].html +1 -1
- fides/ui-build/static/admin/properties/add-property.html +1 -1
- fides/ui-build/static/admin/properties.html +1 -1
- fides/ui-build/static/admin/reporting/datamap.html +1 -1
- fides/ui-build/static/admin/settings/about/alpha.html +1 -1
- fides/ui-build/static/admin/settings/about.html +1 -1
- fides/ui-build/static/admin/settings/consent/[configuration_id]/[purpose_id].html +1 -1
- fides/ui-build/static/admin/settings/consent.html +1 -1
- fides/ui-build/static/admin/settings/custom-fields.html +1 -1
- fides/ui-build/static/admin/settings/domain-records.html +1 -1
- fides/ui-build/static/admin/settings/domains.html +1 -1
- fides/ui-build/static/admin/settings/email-templates.html +1 -1
- fides/ui-build/static/admin/settings/locations.html +1 -1
- fides/ui-build/static/admin/settings/organization.html +1 -1
- fides/ui-build/static/admin/settings/regulations.html +1 -1
- fides/ui-build/static/admin/systems/configure/[id]/test-datasets.html +1 -1
- fides/ui-build/static/admin/systems/configure/[id].html +1 -1
- fides/ui-build/static/admin/systems.html +1 -1
- fides/ui-build/static/admin/taxonomy.html +1 -1
- fides/ui-build/static/admin/user-management/new.html +1 -1
- fides/ui-build/static/admin/user-management/profile/[id].html +1 -1
- fides/ui-build/static/admin/user-management.html +1 -1
- fides/ui-build/static/admin/_next/static/IeU4qLtEtRJo0FsaIFIr8/_buildManifest.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/1817-e601e737e3cc7a0e.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/431-34f0b91c26f8d9ab.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/6780-5bd185892f6af46e.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-2265ecb899d45fbc.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]-8ab33a1e0272df1f.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-32600543eb7b584f.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-10ce53ea356f8bad.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-5501bbb129fee9c4.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-cbe4c8f9096b6543.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/[id]-ff5738706da07801.js +0 -1
- fides/ui-build/static/admin/_next/static/css/2cadb5f62dcd7c2b.css +0 -1
- {ethyca_fides-2.66.1rc0.dist-info → ethyca_fides-2.66.2b1.dist-info}/WHEEL +0 -0
- {ethyca_fides-2.66.1rc0.dist-info → ethyca_fides-2.66.2b1.dist-info}/entry_points.txt +0 -0
- {ethyca_fides-2.66.1rc0.dist-info → ethyca_fides-2.66.2b1.dist-info}/licenses/LICENSE +0 -0
- {ethyca_fides-2.66.1rc0.dist-info → ethyca_fides-2.66.2b1.dist-info}/top_level.txt +0 -0
- /fides/ui-build/static/admin/_next/static/{IeU4qLtEtRJo0FsaIFIr8 → CQD5hIjm-4lH18YYESYuD}/_ssgManifest.js +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{2921-455e6357b74d2f76.js → 2921-86f1547ac40a5cdf.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{3450-0ba194991d0cca88.js → 3450-1cc2bb07ed142203.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{3855-e172870d3e21b0dd.js → 3855-e2fa6db53d32c3de.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{3872-46cebf7ec1b31a2b.js → 3872-84b7e380b88b4454.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{3923-6cc911dafccc5f63.js → 3923-13a6b4da2d51bf8f.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{401-1b529d5800aa1f3a.js → 401-3cc1fee61494e3bd.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{409-a257e14acebcd73b.js → 409-45a125437261580c.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{4121-2bc09fc4ddbfe5cb.js → 4121-f50675521dfee6eb.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{4230-60100f7ef3ddcde1.js → 4230-840c287045c88b34.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{4608-bbb7bf511a05c3c2.js → 4608-a8e3100e2806dbff.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{5309-d73339f062763fed.js → 5309-67bdf9001531e972.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{5574-b13021775a15bfd2.js → 5574-9312f97b637d9ee2.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{6084-7178ff6ea6822475.js → 6084-5d7598b7bcb548cf.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{6662-507be5d46e5b719b.js → 6662-efb2cf74641647f2.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{6853-2ad3e08fe6f9f5f2.js → 6853-4f8bf6558f8c6a46.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{6882-6af16fef26c21e06.js → 6882-586b84aeb02d5830.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{6954-bb875d9ac89f6030.js → 6954-34e062e4bffc7e71.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{7476-281ee9a8286556f3.js → 7476-d206c11823c91088.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{7630-9aac73191ed5ed13.js → 7630-b1c93688013ef013.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{787-fb41002f797eb2df.js → 787-cbe2d0bfb513d90a.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{79-7e87aff851423d4a.js → 79-3db1941d274f40c7.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{796-329a5f823ec258a5.js → 796-98d4bd68909fbe1e.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{9046-ce9567c9074563e2.js → 9046-54877976a0529de2.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{9226-746771d47dff6266.js → 9226-72ad691ca57b83ef.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{9826-111aaee8bd8dbd09.js → 9826-3c578665c6d3b21d.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{9951-9b753ad7c3f51bdf.js → 9951-595d0f1588215081.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{404-aece2c920ea14514.js → 404-2d803dab6a00f353.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{manual-98777246bec9dc2a.js → manual-acb59f8b5e97512a.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{multiple-dc75dc6e37e52f05.js → multiple-8ff7f37913ad736a.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{add-systems-a71c0aff4e0e6535.js → add-systems-0943633a8e422695.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure/{add-vendors-24d226b5a8de5c74.js → add-vendors-d00c9034cdeb0236.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{configure-6a8ef51138ac926a.js → configure-0e1ca0f4c8e7f4da.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{[id]-1edf582ba3cd3bbb.js → [id]-fc3a011154a2e1de.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-experience-685771e5f7196d87.js → privacy-experience-09d4408014bcfe1c.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{[id]-6ccedc70dc447089.js → [id]-d67542783ef5ddac.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{new-944bca1cc57985b5.js → new-3f20e8a316bb3d5b.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-notices-84f4bd14ce8673bc.js → privacy-notices-23e9dcd4590312d2.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{properties-6f86ab63a08a6528.js → properties-057cad65e7414a44.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{reporting-afdbd4665657cfa1.js → reporting-8f891957c8944137.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{consent-73d3cbf68f7c3a31.js → consent-e17c56eec8d91371.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]/{[resourceUrn]-11d52f1570759c4d.js → [resourceUrn]-99c9092d65c94807.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/{[projectUrn]-6ba9e160dae64695.js → [projectUrn]-80a6cc8e8573514a.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{projects-32eac8bbd217615a.js → projects-774fecea22ba8852.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/resources/{[resourceUrn]-b83afa5565d0c84e.js → [resourceUrn]-f6bd6aff389cb9fe.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{resources-7648bbd4f6711e4d.js → resources-6c3714ee97a718c1.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{data-catalog-6f630d42ac9fb6b4.js → data-catalog-8a7f9285da66b965.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{action-center-9ddb52ebb7ac4c71.js → action-center-85e140788e251272.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{activity-9aa744d56cdacb0d.js → activity-5af9381f02b2aff6.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/detection/{[resourceUrn]-393e20924c83373e.js → [resourceUrn]-31e6c54794a9883e.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{detection-8733807dad4bc96e.js → detection-2822a423a7ad0550.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/discovery/{[resourceUrn]-14bd7500362ff224.js → [resourceUrn]-6421ce247549c5d6.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{discovery-9e7dfd5a6acc2e8f.js → discovery-3eac407ac5181a3c.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{datamap-7674b97d655c193b.js → datamap-d2b275d83089820d.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/{[...subfieldNames]-c0d2bfd465df20e0.js → [...subfieldNames]-1c98bd0959d9570a.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/{[collectionName]-28280a8a39a6e37c.js → [collectionName]-e548cabda7da32c9.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/dataset/{[datasetId]-006b695e5af5ef24.js → [datasetId]-a8e8b5f4ee7af86c.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/dataset/{new-82fb246d87e58ebd.js → new-513c862c3a707735.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{dataset-20165c31ab1bc7cf.js → dataset-747b7a13289f1cd7.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{[id]-b4a6bcc87d126840.js → [id]-3d22525b3c327b2e.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{new-f95d7b0bbfc58f5a.js → new-d2cad97495e86adb.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{datastore-connection-c391c6fad56eec48.js → datastore-connection-0f29b47402292070.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{index-1919aab9e5834b51.js → index-12ac3e317fc86f21.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/integrations/{[id]-eacabe4a80cb8813.js → [id]-8d83a5518c00fcfc.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{[id]-53fecfb9dd6a1e0c.js → [id]-5627d0d0668077f9.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{add-template-76b01cec5fde10a9.js → add-template-feca66ad5c5fe54a.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{messaging-5094ffea13f32ed9.js → messaging-c1bd3e7adbe8d2d3.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/poc/{ant-components-5c08e8447c45ce44.js → ant-components-64a322d01aae5ca7.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{AntForm-06ad5f34585480aa.js → AntForm-8bca16a7726e7eb2.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikAntFormItem-6f071c2bc9446cb0.js → FormikAntFormItem-b0f246fc3b67ebf7.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikControlled-efcc38c58991ac9e.js → FormikControlled-1a0852b090bfc392.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikField-430ba5c979abfb7c.js → FormikField-11f3de1b45e36583.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/poc/{forms-5c561880bf131afb.js → forms-1b73a1c2b6c6285f.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/{configure-d888a69a3bbe040e.js → configure-e551a860ec727802.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/properties/{[id]-d3d8e3d7583ec635.js → [id]-dd99183f93763ae4.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/properties/{add-property-1af10ed303815d46.js → add-property-0bdbc1fcbf553b8f.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{properties-cebc0dc186be499a.js → properties-e959378bb32b6b73.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/reporting/{datamap-e130c0197362e8f3.js → datamap-2a98bd257edd8f47.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/settings/about/{alpha-5e1322de868d615e.js → alpha-8f98a4895e74725e.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{about-241f95e372b65d0f.js → about-8155a35a62fdb5ae.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent/[configuration_id]/{[purpose_id]-fc201657f4a782c7.js → [purpose_id]-668d74c041d74650.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{consent-c2d39cba8396ef3a.js → consent-a989532a12c40dcf.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{custom-fields-d992103cc55901ae.js → custom-fields-45bea76ff7eda3cb.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domain-records-41242f805599feda.js → domain-records-51333dbd21cb37c8.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domains-2e885f74c92f669c.js → domains-bde86e5f6c09da5a.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{email-templates-ff112655ad5f41e5.js → email-templates-4f9a5cc8bea7725b.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{locations-023e1895552817de.js → locations-6946e78a5d43e654.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{organization-ac403c0886b20e20.js → organization-55a10e01dffc8039.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{regulations-86062a18e081a52a.js → regulations-102efd9199e87124.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/{test-datasets-7a3396ac819c7904.js → test-datasets-f91f22cf96566ed4.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/{[id]-8314a819837f5b2a.js → [id]-d4a57ea18935dd70.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{systems-21f423a7c417aa9d.js → systems-648a0ff4920579ce.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{taxonomy-6387fcc8cce872eb.js → taxonomy-0b9d1a24188f65a9.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/user-management/{new-a2524414e968f862.js → new-bc4eb541906781e6.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{user-management-173ac3a1ed2b05a6.js → user-management-45bfa04e45a7d13f.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{webpack-ff0cd6bff75588da.js → webpack-63a0c45b150a1037.js} +0 -0
|
File without changes
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import operator as py_operator
|
|
2
|
+
from typing import Any, Union
|
|
3
|
+
|
|
4
|
+
from loguru import logger
|
|
5
|
+
from sqlalchemy.orm import Session
|
|
6
|
+
|
|
7
|
+
from fides.api.graph.config import FieldPath
|
|
8
|
+
from fides.api.task.conditional_dependencies.schemas import (
|
|
9
|
+
Condition,
|
|
10
|
+
ConditionGroup,
|
|
11
|
+
ConditionLeaf,
|
|
12
|
+
GroupOperator,
|
|
13
|
+
Operator,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
operator_methods = {
|
|
17
|
+
Operator.exists: lambda a, _: a is not None,
|
|
18
|
+
Operator.not_exists: lambda a, _: a is None,
|
|
19
|
+
Operator.eq: py_operator.eq,
|
|
20
|
+
Operator.neq: py_operator.ne,
|
|
21
|
+
Operator.lt: lambda a, b: a < b if a is not None else False,
|
|
22
|
+
Operator.lte: lambda a, b: a <= b if a is not None else False,
|
|
23
|
+
Operator.gt: lambda a, b: a > b if a is not None else False,
|
|
24
|
+
Operator.gte: lambda a, b: a >= b if a is not None else False,
|
|
25
|
+
Operator.list_contains: lambda a, b: b in a if isinstance(a, list) else False,
|
|
26
|
+
Operator.not_in_list: lambda a, b: a not in b if isinstance(b, list) else True,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class ConditionEvaluator:
|
|
31
|
+
"""Evaluates nested conditions for manual task creation"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, db: Session):
|
|
34
|
+
self.db = db
|
|
35
|
+
|
|
36
|
+
def evaluate_rule(self, rule: Condition, data: Union[dict, Any]) -> bool:
|
|
37
|
+
"""Evaluate a nested condition rule against input data"""
|
|
38
|
+
if isinstance(rule, ConditionLeaf):
|
|
39
|
+
return self._evaluate_leaf_condition(rule, data)
|
|
40
|
+
# ConditionGroup
|
|
41
|
+
return self._evaluate_group_condition(rule, data)
|
|
42
|
+
|
|
43
|
+
def _evaluate_leaf_condition(
|
|
44
|
+
self, condition: ConditionLeaf, data: Union[dict, Any]
|
|
45
|
+
) -> bool:
|
|
46
|
+
"""Evaluate a leaf condition against input data"""
|
|
47
|
+
actual_value = self._get_nested_value(data, condition.field_address.split("."))
|
|
48
|
+
# Apply operator and return result
|
|
49
|
+
return self._apply_operator(actual_value, condition.operator, condition.value)
|
|
50
|
+
|
|
51
|
+
def _evaluate_group_condition(
|
|
52
|
+
self, group: ConditionGroup, data: Union[dict, Any]
|
|
53
|
+
) -> bool:
|
|
54
|
+
"""Evaluate a group condition against input data"""
|
|
55
|
+
results = [
|
|
56
|
+
self.evaluate_rule(condition, data) for condition in group.conditions
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
logical_operators = {GroupOperator.and_: all, GroupOperator.or_: any}
|
|
60
|
+
operator_func = logical_operators.get(group.logical_operator)
|
|
61
|
+
|
|
62
|
+
if operator_func is None:
|
|
63
|
+
logger.warning(f"Unknown logical operator: {group.logical_operator}")
|
|
64
|
+
return False
|
|
65
|
+
|
|
66
|
+
return operator_func(results)
|
|
67
|
+
|
|
68
|
+
def _get_nested_value(self, data: Union[dict, Any], keys: list[str]) -> Any:
|
|
69
|
+
"""Get nested value from data using dot notation
|
|
70
|
+
|
|
71
|
+
Supports both simple dictionary access and Fides reference structures:
|
|
72
|
+
- Simple dict: data["user"]["name"]
|
|
73
|
+
- Fides FieldAddress: data.get_field_value(FieldAddress("dataset", "collection", "field_address"))
|
|
74
|
+
- Fides Collection: data.get_field_value(FieldPath("field_address", "subfield"))
|
|
75
|
+
"""
|
|
76
|
+
if not keys:
|
|
77
|
+
return data
|
|
78
|
+
|
|
79
|
+
current = data
|
|
80
|
+
|
|
81
|
+
# Try Fides reference structures first
|
|
82
|
+
if hasattr(current, "get_field_value"):
|
|
83
|
+
try:
|
|
84
|
+
field_path = FieldPath(*keys) if len(keys) > 1 else FieldPath(keys[0])
|
|
85
|
+
return current.get_field_value(field_path)
|
|
86
|
+
except (AttributeError, ValueError):
|
|
87
|
+
pass
|
|
88
|
+
|
|
89
|
+
# Fall back to dictionary access
|
|
90
|
+
for key in keys:
|
|
91
|
+
if not isinstance(current, dict):
|
|
92
|
+
current = current.get(key, {}) if hasattr(current, "get") else None
|
|
93
|
+
else:
|
|
94
|
+
current = current.get(key, {})
|
|
95
|
+
|
|
96
|
+
return current if current != {} else None
|
|
97
|
+
|
|
98
|
+
def _apply_operator(
|
|
99
|
+
self, actual_value: Any, operator: Operator, expected_value: Any
|
|
100
|
+
) -> bool:
|
|
101
|
+
"""Apply operator to actual and expected values"""
|
|
102
|
+
|
|
103
|
+
# Get the method for the operator and execute it
|
|
104
|
+
operator_method = operator_methods.get(operator)
|
|
105
|
+
if operator_method is None:
|
|
106
|
+
logger.warning(f"Unknown operator: {operator}")
|
|
107
|
+
return False
|
|
108
|
+
|
|
109
|
+
return operator_method(actual_value, expected_value)
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import List, Optional, Union
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel, Field, model_validator
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Operator(str, Enum):
|
|
8
|
+
eq = "eq"
|
|
9
|
+
neq = "neq"
|
|
10
|
+
lt = "lt"
|
|
11
|
+
lte = "lte"
|
|
12
|
+
gt = "gt"
|
|
13
|
+
gte = "gte"
|
|
14
|
+
exists = "exists"
|
|
15
|
+
not_exists = "not_exists"
|
|
16
|
+
list_contains = "list_contains"
|
|
17
|
+
not_in_list = "not_in_list"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class GroupOperator(str, Enum):
|
|
21
|
+
and_ = "and"
|
|
22
|
+
or_ = "or"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# Leaf condition (e.g., "user.name exists", "user.created_at >= 2024-01-01")
|
|
26
|
+
class ConditionLeaf(BaseModel):
|
|
27
|
+
field_address: str = Field(
|
|
28
|
+
description="Field path to check (e.g., 'user.name', 'billing.subscription.status')"
|
|
29
|
+
)
|
|
30
|
+
operator: Operator = Field(description="Operator to apply")
|
|
31
|
+
value: Optional[
|
|
32
|
+
Union[str, int, float, bool, List[Union[str, int, float, bool]]]
|
|
33
|
+
] = Field(default=None, description="Expected value for comparison")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# Nested logical condition (AND, OR)
|
|
37
|
+
class ConditionGroup(BaseModel):
|
|
38
|
+
logical_operator: GroupOperator = Field(
|
|
39
|
+
description="Logical operator: 'and' or 'or'"
|
|
40
|
+
)
|
|
41
|
+
conditions: list["Condition"] = Field(
|
|
42
|
+
description="List of conditions or nested groups"
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
@model_validator(mode="after")
|
|
46
|
+
def validate_conditions(self) -> "ConditionGroup":
|
|
47
|
+
if not self.conditions:
|
|
48
|
+
raise ValueError("conditions list cannot be empty")
|
|
49
|
+
return self
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# Use model_rebuild to allow recursive nesting
|
|
53
|
+
Condition = Union[ConditionLeaf, ConditionGroup]
|
|
54
|
+
ConditionGroup.model_rebuild()
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# pylint: disable=too-many-lines
|
|
2
|
+
from functools import partial
|
|
2
3
|
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union
|
|
3
4
|
|
|
4
5
|
import dask
|
|
@@ -252,16 +253,33 @@ def run_erasure_request_deprecated( # pylint: disable = too-many-arguments
|
|
|
252
253
|
|
|
253
254
|
access_request_data[ROOT_COLLECTION_ADDRESS.value] = [identity]
|
|
254
255
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
256
|
+
# Build the dask task graph for erasure, ensuring we also pass along the
|
|
257
|
+
# upstream access data that may be required by the connector (e.g. BigQuery
|
|
258
|
+
# delete statements). We accomplish this by partially applying the
|
|
259
|
+
# `inputs` kwarg on each task's `erasure_request` method. The resulting
|
|
260
|
+
# callable accepts the original positional arguments expected by Dask.
|
|
261
|
+
|
|
262
|
+
dsk: Dict[CollectionAddress, Any] = {}
|
|
263
|
+
for k, t in env.items():
|
|
264
|
+
# Collect upstream access data in the same order as the input keys
|
|
265
|
+
upstream_access_data: List[List[Row]] = [
|
|
266
|
+
access_request_data.get(str(input_key), [])
|
|
267
|
+
for input_key in t.execution_node.input_keys
|
|
268
|
+
]
|
|
269
|
+
|
|
270
|
+
# Bind the `inputs` keyword argument so it is supplied when the task executes
|
|
271
|
+
erasure_fn_with_inputs = partial(
|
|
272
|
+
t.erasure_request, inputs=upstream_access_data
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
# Build the task tuple: (callable, retrieved_data, *prereqs)
|
|
276
|
+
dsk[k] = (
|
|
277
|
+
erasure_fn_with_inputs,
|
|
258
278
|
access_request_data.get(
|
|
259
279
|
str(k), []
|
|
260
|
-
), #
|
|
280
|
+
), # Data retrieved for this collection
|
|
261
281
|
*_evaluate_erasure_dependencies(t, erasure_end_nodes),
|
|
262
282
|
)
|
|
263
|
-
for k, t in env.items()
|
|
264
|
-
}
|
|
265
283
|
|
|
266
284
|
# root node returns 0 to be consistent with the output of the other erasure tasks
|
|
267
285
|
dsk[ROOT_COLLECTION_ADDRESS] = 0
|
|
@@ -298,17 +298,11 @@ def run_access_node(
|
|
|
298
298
|
)
|
|
299
299
|
# Currently, upstream tasks and "input keys" (which are built by data dependencies)
|
|
300
300
|
# are the same, but they may not be the same in the future.
|
|
301
|
-
|
|
302
|
-
|
|
301
|
+
upstream_access_data: List[List[Row]] = (
|
|
302
|
+
_build_upstream_access_data(
|
|
303
303
|
graph_task.execution_node.input_keys, upstream_results
|
|
304
304
|
)
|
|
305
305
|
)
|
|
306
|
-
# Pass in access data dependencies in the same order as the input keys.
|
|
307
|
-
# If we don't have access data for an upstream node, pass in an empty list
|
|
308
|
-
upstream_access_data: List[List[Row]] = [
|
|
309
|
-
upstream.get_access_data() if upstream else []
|
|
310
|
-
for upstream in ordered_upstream_tasks
|
|
311
|
-
]
|
|
312
306
|
# Run the main access function
|
|
313
307
|
graph_task.access_request(*upstream_access_data)
|
|
314
308
|
|
|
@@ -359,7 +353,7 @@ def run_erasure_node(
|
|
|
359
353
|
session,
|
|
360
354
|
) as resources:
|
|
361
355
|
# Build GraphTask resource to facilitate execution
|
|
362
|
-
|
|
356
|
+
erasure_graph_task: GraphTask = create_graph_task(
|
|
363
357
|
session, request_task, resources
|
|
364
358
|
)
|
|
365
359
|
# Get access data that was saved in the erasure format that was collected from the
|
|
@@ -368,8 +362,24 @@ def run_erasure_node(
|
|
|
368
362
|
request_task.get_data_for_erasures() or []
|
|
369
363
|
)
|
|
370
364
|
|
|
371
|
-
|
|
372
|
-
|
|
365
|
+
upstream_access_data: List[List[Row]] = []
|
|
366
|
+
|
|
367
|
+
try:
|
|
368
|
+
upstream_access_data = (
|
|
369
|
+
get_upstream_access_data_for_erasure_task(
|
|
370
|
+
request_task, session, resources
|
|
371
|
+
)
|
|
372
|
+
)
|
|
373
|
+
except Exception as e:
|
|
374
|
+
logger.error(
|
|
375
|
+
f"Unable to get upstream access data for erasure task {request_task.collection_address}: {e}"
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
# Run the main erasure function, passing along the upstream access data.
|
|
379
|
+
# The extra data is currently only needed for generating BigQuery delete statements.
|
|
380
|
+
erasure_graph_task.erasure_request(
|
|
381
|
+
retrieved_data, inputs=upstream_access_data
|
|
382
|
+
)
|
|
373
383
|
|
|
374
384
|
queue_downstream_tasks_with_retries(
|
|
375
385
|
self,
|
|
@@ -487,6 +497,73 @@ def _order_tasks_by_input_key(
|
|
|
487
497
|
return tasks
|
|
488
498
|
|
|
489
499
|
|
|
500
|
+
def get_upstream_access_data_for_erasure_task(
|
|
501
|
+
erasure_request_task: RequestTask,
|
|
502
|
+
session: Session,
|
|
503
|
+
resources: TaskResources,
|
|
504
|
+
) -> List[List[Row]]:
|
|
505
|
+
"""
|
|
506
|
+
Retrieves upstream access data for a given erasure request task.
|
|
507
|
+
|
|
508
|
+
This function finds the corresponding access task for the erasure task,
|
|
509
|
+
creates a GraphTask to extract input keys, and builds the upstream access data
|
|
510
|
+
needed for erasure operations (particularly for BigQuery delete statements).
|
|
511
|
+
|
|
512
|
+
Args:
|
|
513
|
+
erasure_request_task: The erasure task that needs upstream access data
|
|
514
|
+
session: Database session for querying
|
|
515
|
+
resources: Task resources for creating GraphTask
|
|
516
|
+
|
|
517
|
+
Returns:
|
|
518
|
+
List[List[Row]]: Upstream access data ordered by input keys
|
|
519
|
+
|
|
520
|
+
Raises:
|
|
521
|
+
Exception: If the corresponding access task cannot be found
|
|
522
|
+
"""
|
|
523
|
+
# Get the corresponding access task for the current erasure task
|
|
524
|
+
access_request_task = (
|
|
525
|
+
session.query(RequestTask)
|
|
526
|
+
.filter(
|
|
527
|
+
RequestTask.privacy_request_id == erasure_request_task.privacy_request_id,
|
|
528
|
+
RequestTask.collection_address == erasure_request_task.collection_address,
|
|
529
|
+
RequestTask.action_type == ActionType.access,
|
|
530
|
+
)
|
|
531
|
+
.first()
|
|
532
|
+
)
|
|
533
|
+
|
|
534
|
+
if not access_request_task:
|
|
535
|
+
raise Exception(
|
|
536
|
+
f"Unable to find access request task for erasure task {erasure_request_task.collection_address}"
|
|
537
|
+
)
|
|
538
|
+
|
|
539
|
+
# Convert the request task to a GraphTask to get the input_keys
|
|
540
|
+
access_graph_task: GraphTask = create_graph_task(
|
|
541
|
+
session, access_request_task, resources
|
|
542
|
+
)
|
|
543
|
+
|
|
544
|
+
# Build and return the upstream access data
|
|
545
|
+
return _build_upstream_access_data(
|
|
546
|
+
access_graph_task.execution_node.input_keys,
|
|
547
|
+
access_request_task.upstream_tasks_objects(session),
|
|
548
|
+
)
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
def _build_upstream_access_data(
|
|
552
|
+
input_keys: List[CollectionAddress],
|
|
553
|
+
upstream_tasks: Query,
|
|
554
|
+
) -> List[List[Row]]:
|
|
555
|
+
"""
|
|
556
|
+
Helper function to build the access data for the current node.
|
|
557
|
+
The access data is passed in the same order as the input keys.
|
|
558
|
+
If we don't have access data for an upstream node, return an empty list.
|
|
559
|
+
"""
|
|
560
|
+
|
|
561
|
+
ordered_upstream: List[Optional[RequestTask]] = _order_tasks_by_input_key(
|
|
562
|
+
input_keys, upstream_tasks
|
|
563
|
+
)
|
|
564
|
+
return [task.get_access_data() if task else [] for task in ordered_upstream]
|
|
565
|
+
|
|
566
|
+
|
|
490
567
|
mapping = {
|
|
491
568
|
ActionType.access.value: run_access_node,
|
|
492
569
|
ActionType.erasure.value: run_erasure_node,
|
fides/api/task/graph_task.py
CHANGED
|
@@ -421,6 +421,7 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
|
|
|
421
421
|
action_type: ActionType,
|
|
422
422
|
ex: Optional[BaseException] = None,
|
|
423
423
|
success_override_msg: Optional[str] = None,
|
|
424
|
+
record_count: Optional[int] = None,
|
|
424
425
|
) -> None:
|
|
425
426
|
"""On completion activities"""
|
|
426
427
|
if ex:
|
|
@@ -440,8 +441,23 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
|
|
|
440
441
|
mark_current_and_downstream_nodes_as_failed(request_task, db)
|
|
441
442
|
else:
|
|
442
443
|
logger.info("Ending {}, {}", self.resources.request.id, self.key)
|
|
444
|
+
|
|
445
|
+
# Build standardized success message with record count
|
|
446
|
+
base_message = (
|
|
447
|
+
str(success_override_msg) if success_override_msg else "success"
|
|
448
|
+
)
|
|
449
|
+
if record_count is not None:
|
|
450
|
+
if action_type == ActionType.access:
|
|
451
|
+
message = f"{base_message} - retrieved {record_count} records"
|
|
452
|
+
elif action_type == ActionType.erasure:
|
|
453
|
+
message = f"{base_message} - masked {record_count} records"
|
|
454
|
+
else:
|
|
455
|
+
message = f"{base_message} - processed {record_count} records"
|
|
456
|
+
else:
|
|
457
|
+
message = base_message
|
|
458
|
+
|
|
443
459
|
self.update_status(
|
|
444
|
-
|
|
460
|
+
message,
|
|
445
461
|
build_affected_field_logs(
|
|
446
462
|
self.execution_node, self.resources.policy, action_type
|
|
447
463
|
),
|
|
@@ -637,7 +653,11 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
|
|
|
637
653
|
if messages:
|
|
638
654
|
success_message = "\n".join(messages)
|
|
639
655
|
|
|
640
|
-
self.log_end(
|
|
656
|
+
self.log_end(
|
|
657
|
+
ActionType.access,
|
|
658
|
+
success_override_msg=success_message,
|
|
659
|
+
record_count=len(filtered_output),
|
|
660
|
+
)
|
|
641
661
|
return filtered_output
|
|
642
662
|
|
|
643
663
|
@retry(action_type=ActionType.erasure, default_return=0)
|
|
@@ -645,9 +665,15 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
|
|
|
645
665
|
self,
|
|
646
666
|
retrieved_data: List[Row],
|
|
647
667
|
*erasure_prereqs: int, # TODO Remove when we stop support for DSR 2.0. DSR 3.0 enforces with downstream_tasks.
|
|
668
|
+
inputs: Optional[
|
|
669
|
+
List[List[Row]]
|
|
670
|
+
] = None, # Upstream data from corresponding access task
|
|
648
671
|
) -> int:
|
|
649
672
|
"""Run erasure request"""
|
|
650
673
|
|
|
674
|
+
if inputs is None:
|
|
675
|
+
inputs = []
|
|
676
|
+
|
|
651
677
|
# if there is no primary key specified in the graph node configuration
|
|
652
678
|
# note this in the execution log and perform no erasures on this node
|
|
653
679
|
if (
|
|
@@ -694,6 +720,10 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
|
|
|
694
720
|
)
|
|
695
721
|
return 0
|
|
696
722
|
|
|
723
|
+
formatted_input_data: NodeInput = self.pre_process_input_data(
|
|
724
|
+
*inputs, group_dependent_fields=True
|
|
725
|
+
)
|
|
726
|
+
|
|
697
727
|
# Use execution context to capture postprocessor messages
|
|
698
728
|
with collect_execution_log_messages() as messages:
|
|
699
729
|
output = self.connector.mask_data(
|
|
@@ -702,6 +732,7 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
|
|
|
702
732
|
self.resources.request,
|
|
703
733
|
self.resources.privacy_request_task,
|
|
704
734
|
retrieved_data,
|
|
735
|
+
formatted_input_data,
|
|
705
736
|
)
|
|
706
737
|
|
|
707
738
|
if self.request_task.id:
|
|
@@ -720,7 +751,11 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
|
|
|
720
751
|
if messages:
|
|
721
752
|
success_message = "\n".join(messages)
|
|
722
753
|
|
|
723
|
-
self.log_end(
|
|
754
|
+
self.log_end(
|
|
755
|
+
ActionType.erasure,
|
|
756
|
+
success_override_msg=success_message,
|
|
757
|
+
record_count=output,
|
|
758
|
+
)
|
|
724
759
|
return output
|
|
725
760
|
|
|
726
761
|
@retry(action_type=ActionType.consent, default_return=False)
|
|
@@ -268,6 +268,7 @@ class ManualTaskGraphTask(GraphTask):
|
|
|
268
268
|
self,
|
|
269
269
|
retrieved_data: List[Row],
|
|
270
270
|
*erasure_prereqs: int, # noqa: D401, pylint: disable=unused-argument
|
|
271
|
+
inputs: Optional[List[List[Row]]] = None,
|
|
271
272
|
) -> int:
|
|
272
273
|
"""Execute manual-task-driven erasure logic.
|
|
273
274
|
|
fides/api/util/cache.py
CHANGED
|
@@ -387,3 +387,8 @@ def get_queue_counts() -> Dict[str, int]:
|
|
|
387
387
|
logger.critical(exception)
|
|
388
388
|
queue_counts = {}
|
|
389
389
|
return queue_counts
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
def get_all_masking_secret_keys(privacy_request_id: str) -> List[str]:
|
|
393
|
+
cache: FidesopsRedis = get_cache()
|
|
394
|
+
return cache.keys(f"id-{privacy_request_id}-masking-secret-*")
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import secrets
|
|
2
|
-
from typing import Dict, List, Optional, TypeVar
|
|
2
|
+
from typing import Any, Dict, List, Optional, TypeVar
|
|
3
3
|
|
|
4
4
|
from loguru import logger
|
|
5
5
|
|
|
6
|
+
from fides.api.db.session import get_db_session
|
|
7
|
+
from fides.api.models.masking_secret import MaskingSecret
|
|
6
8
|
from fides.api.schemas.masking.masking_secrets import (
|
|
7
9
|
MaskingSecretCache,
|
|
8
10
|
MaskingSecretMeta,
|
|
9
11
|
SecretType,
|
|
10
12
|
)
|
|
11
13
|
from fides.api.util.cache import get_cache, get_masking_secret_cache_key
|
|
14
|
+
from fides.config import CONFIG
|
|
12
15
|
|
|
13
16
|
T = TypeVar("T")
|
|
14
17
|
|
|
@@ -21,12 +24,14 @@ class SecretsUtil:
|
|
|
21
24
|
masking_secret_meta: MaskingSecretMeta[T],
|
|
22
25
|
) -> Optional[T]:
|
|
23
26
|
if privacy_request_id is not None:
|
|
24
|
-
secret = SecretsUtil.
|
|
25
|
-
privacy_request_id,
|
|
27
|
+
secret = SecretsUtil.get_masking_secret(
|
|
28
|
+
privacy_request_id=privacy_request_id,
|
|
29
|
+
masking_strategy=masking_secret_meta.masking_strategy,
|
|
30
|
+
secret_type=secret_type,
|
|
26
31
|
)
|
|
27
32
|
if not secret:
|
|
28
33
|
logger.warning(
|
|
29
|
-
"Secret type {} expected
|
|
34
|
+
"Secret type {} expected but was not present for masking strategy {}",
|
|
30
35
|
secret_type,
|
|
31
36
|
masking_secret_meta.masking_strategy,
|
|
32
37
|
)
|
|
@@ -37,20 +42,6 @@ class SecretsUtil:
|
|
|
37
42
|
masking_secret_meta.secret_length
|
|
38
43
|
)
|
|
39
44
|
|
|
40
|
-
@staticmethod
|
|
41
|
-
def _get_secret_from_cache(
|
|
42
|
-
privacy_request_id: str,
|
|
43
|
-
secret_type: SecretType,
|
|
44
|
-
masking_secret_meta: MaskingSecretMeta[T],
|
|
45
|
-
) -> Optional[T]:
|
|
46
|
-
cache = get_cache()
|
|
47
|
-
masking_secret_cache_key: str = get_masking_secret_cache_key(
|
|
48
|
-
privacy_request_id=privacy_request_id,
|
|
49
|
-
masking_strategy=masking_secret_meta.masking_strategy,
|
|
50
|
-
secret_type=secret_type,
|
|
51
|
-
)
|
|
52
|
-
return cache.get_encoded_by_key(masking_secret_cache_key)
|
|
53
|
-
|
|
54
45
|
@staticmethod
|
|
55
46
|
def generate_secret_string(length: int) -> str:
|
|
56
47
|
return secrets.token_urlsafe(length)
|
|
@@ -75,3 +66,42 @@ class SecretsUtil:
|
|
|
75
66
|
)
|
|
76
67
|
)
|
|
77
68
|
return masking_secrets
|
|
69
|
+
|
|
70
|
+
@staticmethod
|
|
71
|
+
def get_masking_secret(
|
|
72
|
+
privacy_request_id: str,
|
|
73
|
+
masking_strategy: str,
|
|
74
|
+
secret_type: SecretType,
|
|
75
|
+
) -> Optional[Any]:
|
|
76
|
+
"""
|
|
77
|
+
Attempts to retrieve masking secret from cache first, then falls back to DB.
|
|
78
|
+
"""
|
|
79
|
+
# TODO: get rid of the cache check after a few releases
|
|
80
|
+
# Try cache first
|
|
81
|
+
cache = get_cache()
|
|
82
|
+
cache_key = get_masking_secret_cache_key(
|
|
83
|
+
privacy_request_id=privacy_request_id,
|
|
84
|
+
masking_strategy=masking_strategy,
|
|
85
|
+
secret_type=secret_type,
|
|
86
|
+
)
|
|
87
|
+
secret = cache.get_encoded_by_key(cache_key)
|
|
88
|
+
if secret is not None:
|
|
89
|
+
return secret
|
|
90
|
+
|
|
91
|
+
# Cache miss - try database
|
|
92
|
+
session_local = get_db_session(CONFIG)
|
|
93
|
+
with session_local() as session:
|
|
94
|
+
masking_secret: MaskingSecret = (
|
|
95
|
+
session.query(MaskingSecret)
|
|
96
|
+
.filter(
|
|
97
|
+
MaskingSecret.privacy_request_id == privacy_request_id,
|
|
98
|
+
MaskingSecret.masking_strategy == masking_strategy,
|
|
99
|
+
MaskingSecret.secret_type == secret_type,
|
|
100
|
+
)
|
|
101
|
+
.first()
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
if not masking_secret:
|
|
105
|
+
return None
|
|
106
|
+
|
|
107
|
+
return masking_secret.get_secret()
|
|
@@ -51,6 +51,7 @@ PRIVACY_REQUEST_ACCESS_RESULTS = "privacy-request-access-results"
|
|
|
51
51
|
PRIVACY_REQUEST_EMAIL_INTEGRATIONS = "privacy-request-email-integrations"
|
|
52
52
|
PRIVACY_REQUEST_NOTIFICATIONS = "privacy-request-notifications"
|
|
53
53
|
READ = "read"
|
|
54
|
+
READ_OWN = "read-own"
|
|
54
55
|
REGISTER = "register"
|
|
55
56
|
RESET = "reset"
|
|
56
57
|
RESPOND = "respond"
|
|
@@ -226,6 +227,7 @@ TAXONOMY_DELETE = f"{TAXONOMY}:{DELETE}"
|
|
|
226
227
|
USER_CREATE = f"{USER}:{CREATE}"
|
|
227
228
|
USER_DELETE = f"{USER}:{DELETE}"
|
|
228
229
|
USER_READ = f"{USER}:{READ}"
|
|
230
|
+
USER_READ_OWN = f"{USER}:{READ_OWN}"
|
|
229
231
|
USER_UPDATE = f"{USER}:{UPDATE}"
|
|
230
232
|
USER_PASSWORD_RESET = f"{USER}:{PASSWORD_RESET}"
|
|
231
233
|
|
|
@@ -354,6 +356,7 @@ SCOPE_DOCS = {
|
|
|
354
356
|
USER_UPDATE: "Update users",
|
|
355
357
|
USER_DELETE: "Remove users",
|
|
356
358
|
USER_READ: "View users",
|
|
359
|
+
USER_READ_OWN: "View own user",
|
|
357
360
|
USER_PASSWORD_RESET: "Reset another user's password",
|
|
358
361
|
USER_PERMISSION_CREATE: "Create user permissions",
|
|
359
362
|
USER_PERMISSION_UPDATE: "Update user permissions",
|
|
@@ -93,7 +93,7 @@ PRIVACY_REQUEST_ACCESS_RESULTS = "/privacy-request/{privacy_request_id}/access-r
|
|
|
93
93
|
PRIVACY_REQUEST_FILTERED_RESULTS = (
|
|
94
94
|
"/privacy-request/{privacy_request_id}/filtered-results"
|
|
95
95
|
)
|
|
96
|
-
|
|
96
|
+
PRIVACY_REQUEST_FINALIZE = "/privacy-request/{privacy_request_id}/finalize"
|
|
97
97
|
PRIVACY_REQUEST_VERIFY_IDENTITY = "/privacy-request/{privacy_request_id}/verify"
|
|
98
98
|
PRIVACY_REQUEST_RESUME = "/privacy-request/{privacy_request_id}/resume"
|
|
99
99
|
PRIVACY_REQUEST_NOTIFICATIONS = "/privacy-request/notification"
|
|
@@ -61,6 +61,10 @@ class ExecutionSettings(FidesSettings):
|
|
|
61
61
|
default=False,
|
|
62
62
|
description="Temporary flag to switch to using DSR 3.0 to process your tasks.",
|
|
63
63
|
)
|
|
64
|
+
erasure_request_finalization_required: bool = Field(
|
|
65
|
+
default=False,
|
|
66
|
+
description="Whether erasure requests require an additional finalization step after all collections have been executed.",
|
|
67
|
+
)
|
|
64
68
|
fuzzy_search_enabled: bool = Field(
|
|
65
69
|
default=True,
|
|
66
70
|
description="Whether fuzzy search is enabled for privacy request lookups.",
|
fides/config/utils.py
CHANGED
|
@@ -193,13 +193,18 @@ class PrivacyRequestService:
|
|
|
193
193
|
|
|
194
194
|
cache_data(
|
|
195
195
|
privacy_request,
|
|
196
|
-
policy,
|
|
197
196
|
privacy_request_data.identity,
|
|
198
197
|
privacy_request_data.encryption_key,
|
|
199
198
|
None,
|
|
200
199
|
privacy_request_data.custom_privacy_request_fields,
|
|
201
200
|
)
|
|
202
201
|
|
|
202
|
+
if masking_secrets := policy.generate_masking_secrets():
|
|
203
|
+
logger.info(
|
|
204
|
+
"Caching masking secrets for privacy request {}", privacy_request.id
|
|
205
|
+
)
|
|
206
|
+
privacy_request.persist_masking_secrets(masking_secrets)
|
|
207
|
+
|
|
203
208
|
check_and_dispatch_error_notifications(db=self.db)
|
|
204
209
|
|
|
205
210
|
_handle_notifications_and_processing(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link data-next-font="" rel="preconnect" href="/" crossorigin="anonymous"/><link rel="preload" href="/_next/static/css/
|
|
1
|
+
<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link data-next-font="" rel="preconnect" href="/" crossorigin="anonymous"/><link rel="preload" href="/_next/static/css/b81194f2c3930152.css" as="style"/><link rel="stylesheet" href="/_next/static/css/b81194f2c3930152.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-63a0c45b150a1037.js" defer=""></script><script src="/_next/static/chunks/framework-c92fc3344e6fd165.js" defer=""></script><script src="/_next/static/chunks/main-090643377c8254e6.js" defer=""></script><script src="/_next/static/chunks/pages/_app-be7889cec5a0f5cd.js" defer=""></script><script src="/_next/static/chunks/pages/404-2d803dab6a00f353.js" defer=""></script><script src="/_next/static/CQD5hIjm-4lH18YYESYuD/_buildManifest.js" defer=""></script><script src="/_next/static/CQD5hIjm-4lH18YYESYuD/_ssgManifest.js" defer=""></script><style>.data-ant-cssinjs-cache-path{content:"";}</style></head><body><div id="__next"><div style="height:100%;display:flex"></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/404","query":{},"buildId":"CQD5hIjm-4lH18YYESYuD","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
|