ethyca-fides 2.62.1rc0__py2.py3-none-any.whl → 2.63.0__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.
- {ethyca_fides-2.62.1rc0.dist-info → ethyca_fides-2.63.0.dist-info}/METADATA +2 -1
- {ethyca_fides-2.62.1rc0.dist-info → ethyca_fides-2.63.0.dist-info}/RECORD +250 -238
- fides/_version.py +3 -3
- fides/api/alembic/migrations/versions/2263583b0e44_add_shared_monitor_config.py +82 -0
- fides/api/alembic/migrations/versions/440a5b9a3493_add_fides_user_respondent_email_.py +80 -0
- fides/api/alembic/migrations/versions/5474a47c77da_create_staged_resource_ancestor_link_table.py +72 -0
- fides/api/alembic/migrations/versions/bf713b5a021d_staged_resource_ancestor_link_data_.py +259 -0
- fides/api/alembic/migrations/versions/c586a56c25e7_remove_child_diff_statuses.py +40 -0
- fides/api/api/v1/endpoints/privacy_request_endpoints.py +2 -2
- fides/api/db/base.py +3 -0
- fides/api/main.py +4 -1
- fides/api/migrations/post_upgrade_index_creation.py +269 -0
- fides/api/models/attachment.py +117 -10
- fides/api/models/audit_log.py +0 -3
- fides/api/models/detection_discovery.py +189 -24
- fides/api/models/fides_user.py +51 -4
- fides/api/models/fides_user_permissions.py +25 -7
- fides/api/models/fides_user_respondent_email_verification.py +112 -0
- fides/api/models/privacy_request/privacy_request.py +40 -1
- fides/api/oauth/roles.py +19 -0
- fides/api/service/connectors/query_configs/saas_query_config.py +3 -8
- fides/api/service/connectors/saas_connector.py +7 -4
- fides/api/service/privacy_request/dsr_package/dsr_report_builder.py +4 -2
- fides/api/service/privacy_request/request_runner_service.py +47 -18
- fides/api/service/privacy_request/request_service.py +4 -15
- fides/api/service/storage/s3.py +40 -15
- fides/api/tasks/storage.py +6 -5
- fides/api/util/lock.py +44 -0
- fides/api/util/storage_util.py +14 -8
- fides/common/api/scope_registry.py +6 -0
- fides/config/config_proxy.py +0 -1
- fides/config/execution_settings.py +0 -4
- fides/ui-build/static/admin/404.html +1 -1
- fides/ui-build/static/admin/_next/static/chunks/1099-667e84655846e78c.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/1100-0b01f500b1eaf60d.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{1817-721fdeb29c07c6be.js → 1817-951f58ddd5d46081.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{1904-7e5354990377a849.js → 1904-361e37a5811ed7fc.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/2310-744354001d01f366.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/2921-49af55ad7c631c93.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/3119-e36ae5071c8f27a5.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/3505-113f9c95d34b7aae.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/3513-5c2d412a84a78971.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/3662-f6a1ddca5ee42076.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/3670-2abd9b2f17770872.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/3872-45cc725e241211f0.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/3923-b4f701ada3ef0ee0.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/3983-17ae9c232bddc413.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/401-7e800aed05537126.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/4060-90a52a9afc655bfc.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/4121-66b0e00d5e7ae817.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/4132-9b1731bfec6ee537.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/4481-7f6710c928bb0cb0.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/5258-2079138c8cc34f6c.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/5404-2694509cf5fa96da.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/5487-2cbd8d2169eb2a65.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/5683-37137111b3e769fb.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/6202-081545c7822d09af.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/6277-459e054b2702c60e.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/641-7e4eef3222cbda70.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/6659-b2088f525bf13c17.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{6853-0cee00c9da26a40e.js → 6853-688df0b88fe65fd5.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/69-00cba94689b9e740.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/6954-4e313b4599b8763d.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/7553-08bc3d9f66695111.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/79-fc548561beed136f.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/796-d6586308ed44334b.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/7980-736f9fd1e749ddd2.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/8032-74d94f7bd5b81c89.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/8433-51870336908fb253.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/8499-1fd392d0be9e8ee4.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/9033-fdd87182c15b91e2.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/9327-6a53461c9764b16f.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{9392.bfca299d4f39a9e0.js → 9392.81edc11e3a175275.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/9494-1ffb888b95289891.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/9676.61cf5f6d6a083175.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/9767-afd674014a1d1152.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/404-ec04f826f3dd79ea.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/{_app-371b155655c83a1e.js → _app-33bc23b79bffe07c.js} +69 -69
- fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/manual-1bec086d567aacff.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/multiple-f68bf100e4e60e88.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/add-systems-effde5cfe49de55f.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure/add-vendors-ec95ed8cb0712828.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure-4cc195e15e0c3cc8.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/[id]-be8972c79fb39705.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{new-7f38473ce267348a.js → new-a0039f216fb3eb93.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience-ccf96207de3b74ea.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/[id]-b9823cc008372cee.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/new-373f5772ab41bc93.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices-b9beeee1bde5ca79.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/properties-6ab3a5baafebd199.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/reporting-8562790ae07f17c9.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/consent-42d4d2d6e0253671.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]/{[resourceUrn]-7ddf45ffd49533b0.js → [resourceUrn]-18e3faf7963962e4.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]-9d1df6d890671b0c.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects-7eb08af333baaa8e.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/resources/{[resourceUrn]-ed213bc1b7041aa2.js → [resourceUrn]-7320524a47104798.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{resources-1f033ca5a0702018.js → resources-51d99174c8006eb5.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog-bb57eed84f59a932.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-47eb34aef3e31ac6.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]-76cefefc53e84c7f.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-9d8e84a8b4bf568d.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/activity-c3eaadd88a2e6caa.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/detection/{[resourceUrn]-f38b3ef885a29ea6.js → [resourceUrn]-4c526db0c30c488a.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{detection-29fd0d5a73f13a00.js → detection-6f27dbb7c8edc69d.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/discovery/{[resourceUrn]-9a80241f1028c470.js → [resourceUrn]-562d2b8ae90dd1f0.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{discovery-c58333981b1522c9.js → discovery-fe7f51502eda57c9.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/datamap-db45aa864e9dda8a.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/[...subfieldNames]-d5cfdebc74654337.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]-618b89228f83435e.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]-12fc86f15a4c764e.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/new-c23d18a9b56c2e3c.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset-e3b2d8e3980ab093.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/[id]-6e27257eccf65f01.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/new-bbac1f624424282d.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection-84eb56f5a07bdf4f.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/index-773182b5e35d0045.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-eb28c927da5bd653.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/integrations-781808bca01f8048.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/messaging/[id]-b51bee8680d66b20.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/messaging/add-template-1de479533f733fbd.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/messaging-7dc295b3ed3d2224.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/ant-components-f64dac3392f5ded7.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/AntForm-eb020bfac4bee532.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/FormikAntFormItem-0bd62e28b539e114.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/FormikControlled-936877004113c2a6.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/FormikField-6416f01524482af9.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/forms-3f4e1313d1f2969b.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/table-migration-1db7a54437db7db0.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-64236fd0141414fd.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-8cab04871908cfeb.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-150d40428245ee0c.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure-b6c876dceb16ad1b.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-20cdb2c8a03deae1.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/properties/[id]-54bcc875592d1fb9.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/properties/add-property-644dc669b508a79a.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/properties-9a88220d03e7e02f.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/reporting/datamap-70dc1081df37ea69.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/about/alpha-3c71b4dbcb6fd6c9.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/about-7cb16e0000dd16c9.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent/[configuration_id]/[purpose_id]-a18d8f12ee8dcf5d.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-dc220e116ad5c09e.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/custom-fields-55ddc5f25b86f28e.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/domain-records-5ca7decded228bc8.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/domains-a6fafa1be2834c40.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/email-templates-e633750d2b45ddd6.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/{locations-4fbab6716326060d.js → locations-3948686cbd372969.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/organization-04ece499c22d23f4.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/regulations-7752305084280cca.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/test-datasets-9e5f9066be6f218d.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]-86de9e6d72098e45.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/systems-cac52e6c3abf6a15.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-60d5930b6855679b.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/[id]-b0f4c34752d32c73.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/{user-management-c0b2113b44f46112.js → user-management-7dee83dd6d9292aa.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{webpack-abd3efcb23c0bb03.js → webpack-8457bad7859c44f0.js} +1 -1
- fides/ui-build/static/admin/_next/static/css/1fdf5c593349dbc6.css +1 -0
- fides/ui-build/static/admin/_next/static/css/5ded47c57dae5baf.css +1 -0
- fides/ui-build/static/admin/_next/static/css/e458b5f1afdbb7fc.css +1 -0
- fides/ui-build/static/admin/_next/static/lb6RRZ8JumokYwsENumlw/_buildManifest.js +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 +2 -2
- fides/ui-build/static/admin/lib/fides.js +2 -2
- 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 -0
- 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 -0
- 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/service/error_handling/__init__.py +0 -0
- fides/service/error_handling/error_handler.py +0 -202
- fides/ui-build/static/admin/_next/static/K1_4-1GhwfL7h4fYYQBvB/_buildManifest.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/1099-98458e8e9ff67508.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/1100-4106d99f5e1ebd75.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/1327-92a38135ee8d55ec.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/2310-0d63c66c2685e83c.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/2921-ca04a0476e2e56c5.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/3119-e441b14cdab4320e.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/3426-e49cb4766324b2dd.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/3505-e58b93f9c1cbdcad.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/3513-87b54d931698986f.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/355-e4340980d72b4faa.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/3615-5e2d062d684b8fa1.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/3872-6b828cb00fb2ce93.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/4060-9593a3f98e600487.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/4121-5c3af879cdd8b3be.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/4294-5b3aa9d605217915.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/4481-8398edf74aabb8ea.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/4723-4c3c7a375e998c15.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/5258-e000d07844eccf7e.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/5487-62955c11bab63734.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/5626-1b636798faad78e1.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/5683-44966a05fa5ad566.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/570-c99f07161bd339cd.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/5826-ce34f25ac2eeb807.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/5973-56d90405c3616068.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/6277-c35c8cc806f7571f.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/6834-dcda0a8ed484775e.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/69-dc52e39d26a4ad14.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/6954-d02d474ba30756b2.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/79-e5884e6878fc1bbb.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/7980-e17dda2f50ec76b8.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/8433-a77c2cd1c1a6887e.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/8499-34a34015c91fc38b.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/9014-eeae6f581158e645.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/9327-a25347d72bfbe680.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/9494-0df032fe6ee531a5.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/9676.97fdbec9c2a48c68.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/9767-74320abc2e9a4550.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/404-c00773c4c6e930af.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/manual-7d789458fb296270.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/multiple-90320455052466cd.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/add-systems-a69f8946466471aa.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure/add-vendors-bcc515a765c0119d.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure-49b9f1b56262dfdc.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/[id]-d4137bb7fdc1ac6e.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience-5ef03041a530b0e2.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/[id]-a5a95ac63b1ce206.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/new-946ce1a2aa1500d4.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices-12f3ba4609bc2ba5.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/properties-ffa15d7ff64a9f05.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/reporting-b959d61c2a3682b3.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent-7797e367dd946a18.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]-ecf23116a845188a.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects-79f8e613827c55c1.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog-e950d41b75f86c85.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-84ead584a88ab662.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]-90f1975f559fff3e.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-4b820a3173f35504.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/activity-beedbc38ee2b0094.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/datamap-2d6f95b2769a0936.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/[...subfieldNames]-3536ae978741b659.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]-8b5afe14cf42a4ac.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]-b8dca4298b5bb085.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/new-1e26702b1a7e0e12.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset-1f0c4e2e5d0b5bf6.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/[id]-ebf54ea9874c59ae.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/new-c39e8e2269883796.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection-9db81467fa254996.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/index-868b60407eae35da.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-ebc41649161f7fb9.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/integrations-b89b9f68ccc69c1b.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/messaging/[id]-22812f08e81bd4f3.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/messaging/add-template-ca22869201847ccc.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/messaging-5f41afae411cd8a4.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/ant-components-173bd3ad45ea61c6.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/AntForm-4dfe984ad80927cd.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/FormikAntFormItem-f790e1ea5cbc26c0.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/FormikControlled-af9e682ec620e990.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/FormikField-6ce407101daa6000.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/forms-9ee8cf14a93eaa4a.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-928430cd40c35ef2.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-07ef58b04404479d.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-595ed9f6ca438020.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure-25a3add8e7982e43.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-b3384299166bcd1e.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/properties/[id]-081f13526443e0a6.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/properties/add-property-17fb474e458b63e7.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/properties-f00530710b699afd.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/reporting/datamap-6a6016708efb5f4f.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/about-177919b4ccf8f660.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent/[configuration_id]/[purpose_id]-ba15c12c89ee10f8.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-0f2daeec241bd1a2.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/custom-fields-0401208a3128fa4d.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/domain-records-0daa256958675a23.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/domains-26810d1ffedcd156.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/email-templates-eb78b645d0c1d4ea.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/organization-9404a6b0b2951992.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/regulations-0a3aa951ef4a44ba.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/test-datasets-48be14ad09ed4133.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]-b03403fed4dd8805.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/systems-ae591953b24e2fc9.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-913efe5371344de6.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/[id]-dc11ba29dbd4708b.js +0 -1
- fides/ui-build/static/admin/_next/static/css/92c81f666644c594.css +0 -1
- fides/ui-build/static/admin/_next/static/css/b89fc4b36b501cf6.css +0 -1
- fides/ui-build/static/admin/_next/static/css/c0c2eb63ad3e7390.css +0 -1
- {ethyca_fides-2.62.1rc0.dist-info → ethyca_fides-2.63.0.dist-info}/WHEEL +0 -0
- {ethyca_fides-2.62.1rc0.dist-info → ethyca_fides-2.63.0.dist-info}/entry_points.txt +0 -0
- {ethyca_fides-2.62.1rc0.dist-info → ethyca_fides-2.63.0.dist-info}/licenses/LICENSE +0 -0
- {ethyca_fides-2.62.1rc0.dist-info → ethyca_fides-2.63.0.dist-info}/top_level.txt +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/user-management/{new-69176abe09cf9b52.js → new-b124cc24b930c9e1.js} +0 -0
- /fides/ui-build/static/admin/_next/static/{K1_4-1GhwfL7h4fYYQBvB → lb6RRZ8JumokYwsENumlw}/_ssgManifest.js +0 -0
@@ -3,15 +3,27 @@ from __future__ import annotations
|
|
3
3
|
from datetime import datetime
|
4
4
|
from enum import Enum
|
5
5
|
from re import match
|
6
|
-
from typing import Any, Dict, Iterable, List, Optional, Type
|
6
|
+
from typing import Any, Dict, Iterable, List, Optional, Set, Type
|
7
7
|
|
8
8
|
from loguru import logger
|
9
|
-
from sqlalchemy import
|
9
|
+
from sqlalchemy import (
|
10
|
+
ARRAY,
|
11
|
+
Boolean,
|
12
|
+
Column,
|
13
|
+
DateTime,
|
14
|
+
ForeignKey,
|
15
|
+
Index,
|
16
|
+
String,
|
17
|
+
UniqueConstraint,
|
18
|
+
func,
|
19
|
+
text,
|
20
|
+
)
|
10
21
|
from sqlalchemy.dialects.postgresql import JSONB
|
11
22
|
from sqlalchemy.ext.asyncio import AsyncSession
|
23
|
+
from sqlalchemy.ext.declarative import declared_attr
|
12
24
|
from sqlalchemy.ext.mutable import MutableDict
|
13
25
|
from sqlalchemy.future import select
|
14
|
-
from sqlalchemy.orm import Session, relationship
|
26
|
+
from sqlalchemy.orm import RelationshipProperty, Session, relationship
|
15
27
|
from sqlalchemy.orm.query import Query
|
16
28
|
|
17
29
|
from fides.api.db.base_class import Base, FidesBase
|
@@ -47,6 +59,29 @@ class MonitorFrequency(Enum):
|
|
47
59
|
QUARTERLY_MONTH_PATTERN = r"^\d+,\d+,\d+,\d+$"
|
48
60
|
|
49
61
|
|
62
|
+
class SharedMonitorConfig(Base, FidesBase):
|
63
|
+
"""SQL model for shareable monitor configurations"""
|
64
|
+
|
65
|
+
@declared_attr
|
66
|
+
def __tablename__(self) -> str:
|
67
|
+
return "shared_monitor_config"
|
68
|
+
|
69
|
+
# Basic info
|
70
|
+
name = Column(String, nullable=False)
|
71
|
+
key = Column(String, unique=True, nullable=False)
|
72
|
+
description = Column(String, nullable=True)
|
73
|
+
|
74
|
+
# Classification parameters (including regex patterns)
|
75
|
+
classify_params = Column(
|
76
|
+
MutableDict.as_mutable(JSONB),
|
77
|
+
index=False,
|
78
|
+
unique=False,
|
79
|
+
nullable=False,
|
80
|
+
server_default="{}",
|
81
|
+
default=dict,
|
82
|
+
)
|
83
|
+
|
84
|
+
|
50
85
|
class MonitorConfig(Base):
|
51
86
|
"""
|
52
87
|
Monitor configuration used for data detection and discovery.
|
@@ -87,7 +122,9 @@ class MonitorConfig(Base):
|
|
87
122
|
) # stores the cron-based kwargs for scheduling the monitor execution.
|
88
123
|
# see https://apscheduler.readthedocs.io/en/3.x/modules/triggers/cron.html
|
89
124
|
|
90
|
-
|
125
|
+
# We use _classify_params for the actual column to prevent direct access
|
126
|
+
_classify_params = Column(
|
127
|
+
"classify_params",
|
91
128
|
MutableDict.as_mutable(JSONB),
|
92
129
|
index=False,
|
93
130
|
unique=False,
|
@@ -124,6 +161,45 @@ class MonitorConfig(Base):
|
|
124
161
|
backref="monitor_config",
|
125
162
|
)
|
126
163
|
|
164
|
+
shared_config_id = Column(
|
165
|
+
String,
|
166
|
+
ForeignKey(SharedMonitorConfig.id_field_path, ondelete="RESTRICT"),
|
167
|
+
nullable=True,
|
168
|
+
index=True,
|
169
|
+
)
|
170
|
+
|
171
|
+
shared_config = relationship(SharedMonitorConfig)
|
172
|
+
|
173
|
+
@property
|
174
|
+
def classify_params(self) -> dict:
|
175
|
+
"""
|
176
|
+
Returns the merged classify parameters from both the monitor config and
|
177
|
+
the shared config (if it exists).
|
178
|
+
|
179
|
+
The shared config parameters take precedence over the monitor's own parameters,
|
180
|
+
but only for values that are not falsy (None, empty, etc.).
|
181
|
+
"""
|
182
|
+
# Start with an empty dict
|
183
|
+
merged_params = {}
|
184
|
+
|
185
|
+
# Add this monitor's params if available
|
186
|
+
if self._classify_params:
|
187
|
+
merged_params.update(self._classify_params)
|
188
|
+
|
189
|
+
# Add/override with shared config params if available
|
190
|
+
if self.shared_config and self.shared_config.classify_params:
|
191
|
+
# Only update with non-falsy values from shared config
|
192
|
+
for key, value in self.shared_config.classify_params.items():
|
193
|
+
if value: # Only override if the value is not falsy
|
194
|
+
merged_params[key] = value
|
195
|
+
|
196
|
+
return merged_params
|
197
|
+
|
198
|
+
@classify_params.setter
|
199
|
+
def classify_params(self, value: Dict[str, Any]) -> None:
|
200
|
+
"""Setter for the classify_params to maintain compatibility with existing code"""
|
201
|
+
self._classify_params = value
|
202
|
+
|
127
203
|
@property
|
128
204
|
def connection_config_key(self) -> str:
|
129
205
|
"""Derives the `connection_config_key`"""
|
@@ -255,6 +331,86 @@ class MonitorConfig(Base):
|
|
255
331
|
data["monitor_execution_trigger"] = cron_trigger_dict
|
256
332
|
|
257
333
|
|
334
|
+
class StagedResourceAncestor(Base):
|
335
|
+
"""
|
336
|
+
A simple junction table that is used to store the many-to-many relationship
|
337
|
+
between staged resources and their ancestors.
|
338
|
+
|
339
|
+
This table is used to easily lookup all ancestors of a given staged resource,
|
340
|
+
as its indexed by both ancestor and descendant URN columns.
|
341
|
+
|
342
|
+
Its entries should be deleted when the staged resource is deleted, via cascade.
|
343
|
+
"""
|
344
|
+
|
345
|
+
ancestor_urn = Column(
|
346
|
+
String,
|
347
|
+
ForeignKey("stagedresource.urn", ondelete="CASCADE"),
|
348
|
+
primary_key=True,
|
349
|
+
nullable=False,
|
350
|
+
)
|
351
|
+
descendant_urn = Column(
|
352
|
+
String,
|
353
|
+
ForeignKey("stagedresource.urn", ondelete="CASCADE"),
|
354
|
+
primary_key=True,
|
355
|
+
nullable=False,
|
356
|
+
)
|
357
|
+
|
358
|
+
ancestor_staged_resource = relationship(
|
359
|
+
"StagedResource",
|
360
|
+
back_populates="ancestor_links",
|
361
|
+
lazy="selectin",
|
362
|
+
foreign_keys=[ancestor_urn],
|
363
|
+
)
|
364
|
+
descendant_staged_resource = relationship(
|
365
|
+
"StagedResource",
|
366
|
+
back_populates="descendant_links",
|
367
|
+
lazy="selectin",
|
368
|
+
foreign_keys=[descendant_urn],
|
369
|
+
)
|
370
|
+
|
371
|
+
__table_args__ = (
|
372
|
+
UniqueConstraint(
|
373
|
+
"ancestor_urn", "descendant_urn", name="uq_staged_resource_ancestor"
|
374
|
+
),
|
375
|
+
Index("ix_staged_resource_ancestor_ancestor", "ancestor_urn"),
|
376
|
+
Index("ix_staged_resource_ancestor_descendant", "descendant_urn"),
|
377
|
+
)
|
378
|
+
|
379
|
+
@classmethod
|
380
|
+
def create_staged_resource_ancestor_links(
|
381
|
+
cls,
|
382
|
+
db: Session,
|
383
|
+
resource_urn: str,
|
384
|
+
ancestor_urns: Set[str],
|
385
|
+
) -> None:
|
386
|
+
"""
|
387
|
+
Bulk inserts entries in the StagedResourceAncestor table
|
388
|
+
based on the provided resource URN and the set of its ancestor URNs.
|
389
|
+
|
390
|
+
We execute the bulk INSERT with the provided (synchronous) db session,
|
391
|
+
but the transaction is _not_ committed, so the caller must commit the transaction
|
392
|
+
to persist the changes.
|
393
|
+
"""
|
394
|
+
links_to_insert = []
|
395
|
+
|
396
|
+
for ancestor_urn in ancestor_urns:
|
397
|
+
links_to_insert.append(
|
398
|
+
{"ancestor_urn": ancestor_urn, "descendant_urn": resource_urn}
|
399
|
+
)
|
400
|
+
|
401
|
+
if links_to_insert:
|
402
|
+
# Using raw SQL for ON CONFLICT with parameters for safety
|
403
|
+
stmt_text = text(
|
404
|
+
"""
|
405
|
+
INSERT INTO stagedresourceancestor (id, ancestor_urn, descendant_urn)
|
406
|
+
VALUES ('srl_' || gen_random_uuid(), :ancestor_urn, :descendant_urn)
|
407
|
+
ON CONFLICT (ancestor_urn, descendant_urn) DO NOTHING;
|
408
|
+
"""
|
409
|
+
)
|
410
|
+
|
411
|
+
db.execute(stmt_text, links_to_insert)
|
412
|
+
|
413
|
+
|
258
414
|
class StagedResource(Base):
|
259
415
|
"""
|
260
416
|
Base DB model that represents a staged resource, fields common to all types of staged resources
|
@@ -331,14 +487,36 @@ class StagedResource(Base):
|
|
331
487
|
parent = Column(String, nullable=True)
|
332
488
|
|
333
489
|
# diff-related fields
|
334
|
-
diff_status = Column(String, nullable=True)
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
490
|
+
diff_status = Column(String, nullable=True, index=True)
|
491
|
+
|
492
|
+
ancestor_links: RelationshipProperty[List[StagedResourceAncestor]] = relationship(
|
493
|
+
"StagedResourceAncestor",
|
494
|
+
back_populates="descendant_staged_resource",
|
495
|
+
lazy="dynamic",
|
496
|
+
cascade="all, delete",
|
497
|
+
foreign_keys=[StagedResourceAncestor.descendant_urn],
|
498
|
+
)
|
499
|
+
|
500
|
+
descendant_links: RelationshipProperty[List[StagedResourceAncestor]] = relationship(
|
501
|
+
"StagedResourceAncestor",
|
502
|
+
back_populates="ancestor_staged_resource",
|
503
|
+
lazy="dynamic",
|
504
|
+
cascade="all, delete",
|
505
|
+
foreign_keys=[StagedResourceAncestor.ancestor_urn],
|
340
506
|
)
|
341
507
|
|
508
|
+
def ancestors(self) -> List[StagedResource]:
|
509
|
+
"""
|
510
|
+
Returns the ancestors of the staged resource
|
511
|
+
"""
|
512
|
+
return [link.ancestor_staged_resource for link in self.ancestor_links]
|
513
|
+
|
514
|
+
def descendants(self) -> List[StagedResource]:
|
515
|
+
"""
|
516
|
+
Returns the descendants of the staged resource
|
517
|
+
"""
|
518
|
+
return [link.descendant_staged_resource for link in self.descendant_links]
|
519
|
+
|
342
520
|
# placeholder for additional attributes
|
343
521
|
meta = Column(
|
344
522
|
MutableDict.as_mutable(JSONB),
|
@@ -391,28 +569,15 @@ class StagedResource(Base):
|
|
391
569
|
)
|
392
570
|
return results.scalars().all()
|
393
571
|
|
394
|
-
def add_child_diff_status(self, diff_status: DiffStatus) -> None:
|
395
|
-
"""Increments the specified child diff status"""
|
396
|
-
self.child_diff_statuses[diff_status.value] = (
|
397
|
-
self.child_diff_statuses.get(diff_status.value, 0) + 1
|
398
|
-
)
|
399
|
-
|
400
572
|
def mark_as_addition(
|
401
573
|
self,
|
402
574
|
db: Session,
|
403
575
|
parent_resource_urns: Iterable[str] = [],
|
404
576
|
) -> None:
|
405
577
|
"""
|
406
|
-
Marks the resource as an addition
|
407
|
-
the given parent resource URNs accordingly
|
578
|
+
Marks the resource as an addition
|
408
579
|
"""
|
409
580
|
self.diff_status = DiffStatus.ADDITION.value
|
410
|
-
for parent_resource_urn in parent_resource_urns:
|
411
|
-
parent_resource: Optional[StagedResource] = StagedResource.get_urn(
|
412
|
-
db, parent_resource_urn
|
413
|
-
)
|
414
|
-
if parent_resource:
|
415
|
-
parent_resource.add_child_diff_status(DiffStatus.ADDITION)
|
416
581
|
|
417
582
|
|
418
583
|
class MonitorExecution(Base):
|
fides/api/models/fides_user.py
CHANGED
@@ -23,12 +23,16 @@ from fides.api.db.base_class import Base
|
|
23
23
|
from fides.api.models.audit_log import AuditLog
|
24
24
|
|
25
25
|
# Intentionally importing SystemManager here to build the FidesUser.systems relationship
|
26
|
-
from fides.api.models.system_manager import SystemManager # type: ignore[unused-import]
|
27
26
|
from fides.api.schemas.user import DisabledReason
|
28
27
|
from fides.config import CONFIG
|
29
28
|
|
30
29
|
if TYPE_CHECKING:
|
30
|
+
from fides.api.models.fides_user_permissions import FidesUserPermissions
|
31
|
+
from fides.api.models.fides_user_respondent_email_verification import (
|
32
|
+
FidesUserRespondentEmailVerification,
|
33
|
+
)
|
31
34
|
from fides.api.models.sql_models import System # type: ignore[attr-defined]
|
35
|
+
from fides.api.models.system_manager import SystemManager
|
32
36
|
|
33
37
|
|
34
38
|
class FidesUser(Base):
|
@@ -71,6 +75,20 @@ class FidesUser(Base):
|
|
71
75
|
)
|
72
76
|
|
73
77
|
systems = relationship("System", secondary="systemmanager", back_populates="data_stewards") # type: ignore
|
78
|
+
# permissions relationship is defined via backref in FidesUserPermissions
|
79
|
+
email_verifications = relationship(
|
80
|
+
"FidesUserRespondentEmailVerification",
|
81
|
+
back_populates="user",
|
82
|
+
cascade="all,delete",
|
83
|
+
lazy="dynamic",
|
84
|
+
foreign_keys="[FidesUserRespondentEmailVerification.user_id]",
|
85
|
+
)
|
86
|
+
permissions = relationship(
|
87
|
+
"FidesUserPermissions",
|
88
|
+
back_populates="user",
|
89
|
+
cascade="all,delete",
|
90
|
+
uselist=False,
|
91
|
+
)
|
74
92
|
|
75
93
|
@property
|
76
94
|
def system_ids(self) -> List[str]:
|
@@ -92,12 +110,11 @@ class FidesUser(Base):
|
|
92
110
|
) -> FidesUser:
|
93
111
|
"""Create a FidesUser by hashing the password with a generated salt
|
94
112
|
and storing the hashed password and the salt"""
|
113
|
+
hashed_password = None
|
114
|
+
salt = None
|
95
115
|
|
96
116
|
if password := data.get("password"):
|
97
117
|
hashed_password, salt = FidesUser.hash_password(password)
|
98
|
-
else:
|
99
|
-
hashed_password = None
|
100
|
-
salt = None
|
101
118
|
|
102
119
|
user = super().create(
|
103
120
|
db,
|
@@ -117,6 +134,18 @@ class FidesUser(Base):
|
|
117
134
|
|
118
135
|
return user # type: ignore
|
119
136
|
|
137
|
+
@classmethod
|
138
|
+
def create_respondent(cls, db: Session, data: dict[str, Any]) -> FidesUser:
|
139
|
+
"""Create a respondent user. This user will not be able to login with a password and
|
140
|
+
requires an email address to be provided.
|
141
|
+
"""
|
142
|
+
if not data.get("email_address"):
|
143
|
+
raise ValueError("Email address is required for external respondents")
|
144
|
+
if data.get("password"):
|
145
|
+
raise ValueError("Password login is not allowed for external respondents")
|
146
|
+
data["password_login_enabled"] = False
|
147
|
+
return cls.create(db, data)
|
148
|
+
|
120
149
|
def credentials_valid(self, password: str, encoding: str = "UTF-8") -> bool:
|
121
150
|
"""Verifies that the provided password is correct."""
|
122
151
|
if self.salt is None:
|
@@ -134,6 +163,9 @@ class FidesUser(Base):
|
|
134
163
|
|
135
164
|
No validations are performed on the old/existing password within this function.
|
136
165
|
"""
|
166
|
+
if self.permissions is not None:
|
167
|
+
if self.permissions.is_respondent():
|
168
|
+
raise ValueError("Password changes are not allowed for respondents")
|
137
169
|
|
138
170
|
hashed_password, salt = FidesUser.hash_password(new_password)
|
139
171
|
self.hashed_password = hashed_password # type: ignore
|
@@ -141,6 +173,17 @@ class FidesUser(Base):
|
|
141
173
|
self.password_reset_at = datetime.utcnow() # type: ignore
|
142
174
|
self.save(db)
|
143
175
|
|
176
|
+
def update_email_address(self, db: Session, new_email_address: str) -> None:
|
177
|
+
"""Updates the user's email address to the specified value."""
|
178
|
+
if self.permissions is not None:
|
179
|
+
if self.permissions.is_respondent():
|
180
|
+
raise ValueError(
|
181
|
+
"Email address changes are not allowed for respondents"
|
182
|
+
)
|
183
|
+
|
184
|
+
self.email_address = new_email_address # type: ignore
|
185
|
+
self.save(db)
|
186
|
+
|
144
187
|
def set_as_system_manager(self, db: Session, system: System) -> None:
|
145
188
|
"""Add a user as one of the system managers for the given system
|
146
189
|
If applicable, also update the systems on the user's client
|
@@ -157,6 +200,10 @@ class FidesUser(Base):
|
|
157
200
|
f"User '{self.username}' is already a system manager of '{system.name}'."
|
158
201
|
)
|
159
202
|
|
203
|
+
if self.permissions is not None:
|
204
|
+
if self.permissions.is_respondent():
|
205
|
+
raise SystemManagerException("Respondents cannot be system managers.")
|
206
|
+
|
160
207
|
self.systems.append(system)
|
161
208
|
self.save(db=db)
|
162
209
|
|
@@ -1,11 +1,15 @@
|
|
1
|
-
from typing import List
|
1
|
+
from typing import List, cast
|
2
2
|
|
3
3
|
from sqlalchemy import ARRAY, Column, ForeignKey, String
|
4
|
-
from sqlalchemy.orm import
|
4
|
+
from sqlalchemy.orm import Session, relationship
|
5
5
|
|
6
6
|
from fides.api.db.base_class import Base
|
7
7
|
from fides.api.models.fides_user import FidesUser
|
8
|
-
from fides.api.oauth.roles import
|
8
|
+
from fides.api.oauth.roles import (
|
9
|
+
EXTERNAL_RESPONDENT,
|
10
|
+
RESPONDENT,
|
11
|
+
ROLES_TO_SCOPES_MAPPING,
|
12
|
+
)
|
9
13
|
|
10
14
|
|
11
15
|
class FidesUserPermissions(Base):
|
@@ -13,10 +17,7 @@ class FidesUserPermissions(Base):
|
|
13
17
|
|
14
18
|
user_id = Column(String, ForeignKey(FidesUser.id), nullable=False, unique=True)
|
15
19
|
roles = Column(ARRAY(String), nullable=False, server_default="{}", default=dict)
|
16
|
-
user = relationship(
|
17
|
-
FidesUser,
|
18
|
-
backref=backref("permissions", cascade="all,delete", uselist=False),
|
19
|
-
)
|
20
|
+
user = relationship(FidesUser, back_populates="permissions", uselist=False)
|
20
21
|
|
21
22
|
@property
|
22
23
|
def total_scopes(self) -> List[str]:
|
@@ -26,3 +27,20 @@ class FidesUserPermissions(Base):
|
|
26
27
|
all_scopes += ROLES_TO_SCOPES_MAPPING.get(role, [])
|
27
28
|
|
28
29
|
return sorted(list(set(all_scopes)))
|
30
|
+
|
31
|
+
def is_respondent(self) -> bool:
|
32
|
+
"""Check if the user is a respondent."""
|
33
|
+
return any(role in self.roles for role in [RESPONDENT, EXTERNAL_RESPONDENT])
|
34
|
+
|
35
|
+
def update_roles(self, db: Session, new_roles: List[str]) -> None:
|
36
|
+
"""Update the user's roles if allowed.
|
37
|
+
Raises ValueError if role changes are not allowed."""
|
38
|
+
if self.is_respondent():
|
39
|
+
raise ValueError("Role changes are not allowed for respondents")
|
40
|
+
|
41
|
+
self.roles = new_roles
|
42
|
+
self.save(db)
|
43
|
+
|
44
|
+
def update(self, db: Session, *, data: dict) -> "FidesUserPermissions":
|
45
|
+
"""Update the user permissions with the provided data."""
|
46
|
+
return cast(FidesUserPermissions, super().update(db, data=data))
|
@@ -0,0 +1,112 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from datetime import datetime, timedelta, timezone
|
4
|
+
from typing import TYPE_CHECKING, Any, Optional
|
5
|
+
|
6
|
+
from sqlalchemy import Column, DateTime, ForeignKey, String
|
7
|
+
from sqlalchemy.ext.declarative import declared_attr
|
8
|
+
from sqlalchemy.orm import Session, relationship
|
9
|
+
|
10
|
+
from fides.api.cryptography.cryptographic_util import generate_secure_random_string
|
11
|
+
from fides.api.db.base_class import Base
|
12
|
+
from fides.api.util.identity_verification import IdentityVerificationMixin
|
13
|
+
from fides.config import get_config
|
14
|
+
|
15
|
+
CONFIG = get_config()
|
16
|
+
|
17
|
+
|
18
|
+
if TYPE_CHECKING:
|
19
|
+
from fides.api.models.fides_user import FidesUser
|
20
|
+
|
21
|
+
# Access links stay active for 45 days - the same as the DSR expiration. A new link is generated for each email.
|
22
|
+
# The emails are created for new DSRs which are assigned to the respondent.
|
23
|
+
ACCESS_LINK_TTL_DAYS = 45
|
24
|
+
|
25
|
+
|
26
|
+
class FidesUserRespondentEmailVerification(Base, IdentityVerificationMixin):
|
27
|
+
"""Model for handling email verification for external respondents.
|
28
|
+
|
29
|
+
This handles two types of verification:
|
30
|
+
1. Access links - long-lived (45 days) for initial access
|
31
|
+
2. Verification codes - short-lived (1 hour) for actual verification
|
32
|
+
|
33
|
+
When an email is sent to an external respondent, a new verification is created with a new access token is created.
|
34
|
+
When a respondent clicks the link in the email, the access token is verified and a verification code is generated.
|
35
|
+
The verification code is sent to the respondent's email address and the respondent is prompted to enter the code.
|
36
|
+
Verification is handled by the `IdentityVerificationMixin` class.
|
37
|
+
"""
|
38
|
+
|
39
|
+
@declared_attr
|
40
|
+
def __tablename__(self) -> str:
|
41
|
+
return "fides_user_respondent_email_verification"
|
42
|
+
|
43
|
+
user_id = Column(
|
44
|
+
String,
|
45
|
+
ForeignKey("fidesuser.id", ondelete="CASCADE"),
|
46
|
+
nullable=False,
|
47
|
+
index=True,
|
48
|
+
)
|
49
|
+
|
50
|
+
access_token = Column(
|
51
|
+
String, nullable=False, unique=True, index=True
|
52
|
+
) # Token for the access link
|
53
|
+
access_token_expires_at = Column(DateTime(timezone=True), nullable=False)
|
54
|
+
identity_verified_at = Column(DateTime(timezone=True), nullable=True)
|
55
|
+
|
56
|
+
user = relationship(
|
57
|
+
"FidesUser",
|
58
|
+
back_populates="email_verifications",
|
59
|
+
foreign_keys=[user_id],
|
60
|
+
)
|
61
|
+
|
62
|
+
@classmethod
|
63
|
+
def create(
|
64
|
+
cls, db: Session, *, data: dict[str, Any], check_name: bool = False
|
65
|
+
) -> FidesUserRespondentEmailVerification:
|
66
|
+
"""
|
67
|
+
Create a FidesUserEmailVerification record with a new access token.
|
68
|
+
The verification code will be generated when the access link is used.
|
69
|
+
"""
|
70
|
+
# Generate a secure token for the access link
|
71
|
+
access_token = generate_secure_random_string(32)
|
72
|
+
expires_at = datetime.now(timezone.utc) + timedelta(days=ACCESS_LINK_TTL_DAYS)
|
73
|
+
|
74
|
+
verification = super().create(
|
75
|
+
db,
|
76
|
+
data={
|
77
|
+
"user_id": data["user_id"],
|
78
|
+
"access_token": access_token,
|
79
|
+
"access_token_expires_at": expires_at,
|
80
|
+
},
|
81
|
+
)
|
82
|
+
|
83
|
+
return verification
|
84
|
+
|
85
|
+
def is_access_token_expired(self) -> bool:
|
86
|
+
"""Check if the access token has expired."""
|
87
|
+
if not self.access_token_expires_at:
|
88
|
+
return True
|
89
|
+
|
90
|
+
current_time_utc = datetime.now(timezone.utc)
|
91
|
+
return current_time_utc > self.access_token_expires_at
|
92
|
+
|
93
|
+
def verify_access_token(self, token: str) -> bool:
|
94
|
+
"""Verify the access token and generate a verification code if valid."""
|
95
|
+
if self.is_access_token_expired():
|
96
|
+
return False
|
97
|
+
|
98
|
+
return self.access_token == token
|
99
|
+
|
100
|
+
def verify_identity(
|
101
|
+
self,
|
102
|
+
db: Session,
|
103
|
+
provided_code: Optional[str] = None,
|
104
|
+
) -> None:
|
105
|
+
"""A method to call the internal identity verification method provided by the
|
106
|
+
`IdentityVerificationMixin`."""
|
107
|
+
if self.is_access_token_expired():
|
108
|
+
raise ValueError("Access token has expired.")
|
109
|
+
|
110
|
+
self._verify_identity(provided_code=provided_code)
|
111
|
+
self.identity_verified_at = datetime.now(timezone.utc)
|
112
|
+
self.save(db)
|
@@ -1089,6 +1089,46 @@ class PrivacyRequest(
|
|
1089
1089
|
if attachment:
|
1090
1090
|
attachment.delete(db)
|
1091
1091
|
|
1092
|
+
def _get_manual_webhook_attachments(
|
1093
|
+
self, db: Session, manual_webhook_id: str, reference_type: str
|
1094
|
+
) -> List[Attachment]:
|
1095
|
+
"""Helper method to get attachments that have references to both this privacy request and the specified manual webhook"""
|
1096
|
+
query = """
|
1097
|
+
SELECT DISTINCT a.*
|
1098
|
+
FROM attachment a
|
1099
|
+
INNER JOIN attachment_reference ar1 ON a.id = ar1.attachment_id
|
1100
|
+
INNER JOIN attachment_reference ar2 ON a.id = ar2.attachment_id
|
1101
|
+
WHERE ar1.reference_id = :privacy_request_id
|
1102
|
+
AND ar1.reference_type = 'privacy_request'
|
1103
|
+
AND ar2.reference_id = :manual_webhook_id
|
1104
|
+
AND ar2.reference_type = :reference_type
|
1105
|
+
"""
|
1106
|
+
result = db.execute(
|
1107
|
+
query,
|
1108
|
+
{
|
1109
|
+
"privacy_request_id": self.id,
|
1110
|
+
"manual_webhook_id": manual_webhook_id,
|
1111
|
+
"reference_type": reference_type,
|
1112
|
+
},
|
1113
|
+
)
|
1114
|
+
return [Attachment(**row) for row in result]
|
1115
|
+
|
1116
|
+
def get_access_manual_webhook_attachments(
|
1117
|
+
self, db: Session, manual_webhook_id: str
|
1118
|
+
) -> List[Attachment]:
|
1119
|
+
"""Get all attachments that have references to both this privacy request and the specified access manual webhook"""
|
1120
|
+
return self._get_manual_webhook_attachments(
|
1121
|
+
db, manual_webhook_id, "access_manual_webhook"
|
1122
|
+
)
|
1123
|
+
|
1124
|
+
def get_erasure_manual_webhook_attachments(
|
1125
|
+
self, db: Session, manual_webhook_id: str
|
1126
|
+
) -> List[Attachment]:
|
1127
|
+
"""Get all attachments that have references to both this privacy request and the specified erasure manual webhook"""
|
1128
|
+
return self._get_manual_webhook_attachments(
|
1129
|
+
db, manual_webhook_id, "erasure_manual_webhook"
|
1130
|
+
)
|
1131
|
+
|
1092
1132
|
def get_existing_request_task(
|
1093
1133
|
self,
|
1094
1134
|
db: Session,
|
@@ -1228,7 +1268,6 @@ class PrivacyRequest(
|
|
1228
1268
|
"""
|
1229
1269
|
if not self.policy.get_rules_for_action(action_type=ActionType.access):
|
1230
1270
|
return None
|
1231
|
-
|
1232
1271
|
self.filtered_final_upload = results
|
1233
1272
|
self.save(db)
|
1234
1273
|
|
fides/api/oauth/roles.py
CHANGED
@@ -27,6 +27,8 @@ from fides.common.api.scope_registry import (
|
|
27
27
|
PRIVACY_NOTICE_READ,
|
28
28
|
PRIVACY_REQUEST_CALLBACK_RESUME,
|
29
29
|
PRIVACY_REQUEST_DELETE,
|
30
|
+
PRIVACY_REQUEST_MANUAL_STEPS_RESPOND,
|
31
|
+
PRIVACY_REQUEST_MANUAL_STEPS_REVIEW,
|
30
32
|
PRIVACY_REQUEST_NOTIFICATIONS_CREATE_OR_UPDATE,
|
31
33
|
PRIVACY_REQUEST_NOTIFICATIONS_READ,
|
32
34
|
PRIVACY_REQUEST_READ,
|
@@ -52,6 +54,8 @@ CONTRIBUTOR = "contributor"
|
|
52
54
|
OWNER = "owner"
|
53
55
|
VIEWER = "viewer"
|
54
56
|
VIEWER_AND_APPROVER = "viewer_and_approver"
|
57
|
+
RESPONDENT = "respondent"
|
58
|
+
EXTERNAL_RESPONDENT = "external_respondent"
|
55
59
|
|
56
60
|
|
57
61
|
class RoleRegistryEnum(Enum):
|
@@ -62,6 +66,8 @@ class RoleRegistryEnum(Enum):
|
|
62
66
|
Approver - Limited viewer but can approve Privacy Requests
|
63
67
|
Viewer + Approver = Full View and can approve Privacy Requests
|
64
68
|
Contributor - Can't configure storage and messaging
|
69
|
+
Respondent - Internal user who can respond to manual steps
|
70
|
+
External Respondent - External user who can only respond to assigned manual steps
|
65
71
|
"""
|
66
72
|
|
67
73
|
owner = OWNER
|
@@ -69,6 +75,8 @@ class RoleRegistryEnum(Enum):
|
|
69
75
|
viewer = VIEWER
|
70
76
|
approver = APPROVER
|
71
77
|
contributor = CONTRIBUTOR
|
78
|
+
respondent = RESPONDENT
|
79
|
+
external_respondent = EXTERNAL_RESPONDENT
|
72
80
|
|
73
81
|
|
74
82
|
approver_scopes = [
|
@@ -79,6 +87,7 @@ approver_scopes = [
|
|
79
87
|
PRIVACY_REQUEST_VIEW_DATA,
|
80
88
|
PRIVACY_REQUEST_DELETE,
|
81
89
|
USER_READ, # allows approver to view user management table and update their own password
|
90
|
+
PRIVACY_REQUEST_MANUAL_STEPS_REVIEW, # allows approvers to see all manual steps
|
82
91
|
]
|
83
92
|
|
84
93
|
|
@@ -114,6 +123,14 @@ viewer_scopes = [ # Intentionally omitted USER_PERMISSION_READ and PRIVACY_REQU
|
|
114
123
|
USER_READ,
|
115
124
|
]
|
116
125
|
|
126
|
+
respondent_scopes = [
|
127
|
+
PRIVACY_REQUEST_MANUAL_STEPS_RESPOND, # allows respondents to respond to assigned manual steps
|
128
|
+
]
|
129
|
+
|
130
|
+
external_respondent_scopes = [
|
131
|
+
PRIVACY_REQUEST_MANUAL_STEPS_RESPOND, # allows external respondents to respond to assigned manual steps
|
132
|
+
]
|
133
|
+
|
117
134
|
not_contributor_scopes = [
|
118
135
|
CONNECTOR_TEMPLATE_REGISTER,
|
119
136
|
STORAGE_CREATE_OR_UPDATE,
|
@@ -130,6 +147,8 @@ ROLES_TO_SCOPES_MAPPING: Dict[str, List] = {
|
|
130
147
|
VIEWER: sorted(viewer_scopes),
|
131
148
|
APPROVER: sorted(approver_scopes),
|
132
149
|
CONTRIBUTOR: sorted(list(set(SCOPE_REGISTRY) - set(not_contributor_scopes))),
|
150
|
+
RESPONDENT: sorted(respondent_scopes),
|
151
|
+
EXTERNAL_RESPONDENT: sorted(external_respondent_scopes),
|
133
152
|
}
|
134
153
|
|
135
154
|
|