ethyca-fides 2.64.6b1__py2.py3-none-any.whl → 2.65.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.
Potentially problematic release.
This version of ethyca-fides might be problematic. Click here for more details.
- {ethyca_fides-2.64.6b1.dist-info → ethyca_fides-2.65.0.dist-info}/METADATA +1 -1
- {ethyca_fides-2.64.6b1.dist-info → ethyca_fides-2.65.0.dist-info}/RECORD +222 -217
- fides/_version.py +3 -3
- fides/api/alembic/migrations/versions/641f6bcd424f_add_user_id_to_manual_task_log.py +28 -0
- fides/api/api/v1/endpoints/generic_overrides.py +13 -3
- fides/api/email_templates/get_email_template.py +4 -1
- fides/api/email_templates/template_names.py +1 -0
- fides/api/email_templates/templates/external_user_welcome.html +23 -0
- fides/api/models/fides_user_respondent_email_verification.py +3 -3
- fides/api/models/manual_task.py +12 -0
- fides/api/oauth/utils.py +11 -0
- fides/api/request_context.py +76 -0
- fides/api/schemas/messaging/messaging.py +14 -0
- fides/api/schemas/saas/strategy_configuration.py +6 -0
- fides/api/service/connectors/saas_connector.py +43 -1
- fides/api/service/execution_context.py +59 -0
- fides/api/service/messaging/message_dispatch_service.py +33 -1
- fides/api/service/processors/post_processor_strategy/__init__.py +1 -0
- fides/api/service/processors/post_processor_strategy/post_processor_strategy.py +11 -1
- fides/api/service/processors/post_processor_strategy/post_processor_strategy_extract_for_execution_log.py +73 -0
- fides/api/service/processors/post_processor_strategy/post_processor_strategy_factory.py +4 -0
- fides/api/service/processors/post_processor_strategy/post_processor_strategy_filter.py +2 -0
- fides/api/service/processors/post_processor_strategy/post_processor_strategy_unwrap.py +2 -0
- fides/api/task/graph_task.py +38 -18
- fides/api/task/manual/manual_task_utils.py +82 -43
- fides/ui-build/static/admin/404.html +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{1040-d246ed641088a416.js → 1040-94f81c731c29246d.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{1817-60f08a3619b9139c.js → 1817-f2f34b8bd569ae1d.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{2921-85515257dd94ef4d.js → 2921-c19da1016b81bda3.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/3450-84ea89e7a0f95470.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{3855-2d045674fbf72a3c.js → 3855-44e1171660633b6f.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{3872-056ddf3ed9d10b51.js → 3872-a7ee651751f5e145.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{3923-257df982a95371b5.js → 3923-5a82816119f8f907.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/3988-046b3a2866b5cb99.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{401-3f2160e3910d075b.js → 401-7fa53f1e774e02fb.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{409-3e2248a63dd60e58.js → 409-03011bbedb4d72f6.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/4121-536e7e853d0833c0.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{4230-38c6e446801a8729.js → 4230-864eac33691cd299.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{431-13b0ef67d5a3df2f.js → 431-458946a2cae21b5d.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{5309-fd8cd5aedd45f7c1.js → 5309-018fe2068151d699.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{5574-028ef28c3cf16995.js → 5574-48d7c9a526a3a0fe.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{6084-fa1c82d03f6c256a.js → 6084-4a1964e1b20c9eee.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/6662-f2c51b0c01603952.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{6853-2644f28976b46c25.js → 6853-19268388843a58f5.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{6882-ea071425d25dd2b0.js → 6882-f807b643776c8d47.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{6954-bb360fb60aac9440.js → 6954-ec0697d355730f74.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{7476-7073ec015f84a3e0.js → 7476-7fc24f19a2cc563a.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{7630-302a13c63f9bfb45.js → 7630-e0e04e495732ae8f.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{787-b393c03ade9d93dc.js → 787-0c18bf9acef937de.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{79-b67ba449b0f2cc9c.js → 79-d4c8900a83eb83bc.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{796-b7608f09607288b8.js → 796-a98f370ec9b5cbf9.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{9046-ece5efe762b810cb.js → 9046-b3dccae317a7bae5.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{9226-c9111590692341b1.js → 9226-a5904e64ab72cb18.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{9392.9a948112de74781b.js → 9392.bb5a989efef5b329.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{9676.cc515c853b8cf578.js → 9676.549c72c3eb3df912.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{9767-277a0229aae7662a.js → 9767-9afc910b855d913a.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{9826-82c473dcaf892d00.js → 9826-7b769d4863df242a.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{9951-dbd76d7f3a7f1b9a.js → 9951-27d79500acfefdd2.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{404-ef01376efb8427e1.js → 404-ac335065bc49f818.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{_app-7430e1499432b029.js → _app-ecf5a5601e266a1e.js} +56 -56
- fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{manual-4057c399f58d331e.js → manual-3964f3039ce3f18c.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{multiple-2726ca51f0327347.js → multiple-a2ae50c2f0e7608e.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{add-systems-a2457d5da25aa854.js → add-systems-4f20f18ec01fd15a.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure/{add-vendors-9fe46ed10a7e7a1a.js → add-vendors-4957c0b6fa498f6e.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/{configure-095828301f22cdaa.js → configure-3ede98dedea9f621.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{[id]-de60a5b74f6b20ff.js → [id]-f285b2dca83711ba.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-experience-1ee05fd0bc012ec6.js → privacy-experience-efa0f3e3991dc139.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{[id]-5a2e61c7d88bdda1.js → [id]-21c96b42424c33bc.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{new-1bc69669215fa55c.js → new-e494f14ce371390c.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-notices-fa8394d2e1072aba.js → privacy-notices-25cb30b4585622d6.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/{properties-213c5405e9e4219c.js → properties-78ba4553dd12d0d3.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/{reporting-44aa77149d71a6fe.js → reporting-b65b5ab73dfcb801.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{consent-23ab7bd613a0ad53.js → consent-87c06e0daf2b2e87.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/{[projectUrn]-dae11464a091537f.js → [projectUrn]-c956a3faed9f922c.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{projects-7442023478422295.js → projects-691e19bdd29b8c3b.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{resources-d8db234a44a2ddf4.js → resources-7648bbd4f6711e4d.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{data-catalog-5597d2e691313bb0.js → data-catalog-b1616ecfd86a2e2e.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/{[systemId]-da06d05d255d0cd0.js → [systemId]-052028439e802c76.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/{[monitorId]-895591fe32af0f4c.js → [monitorId]-99d3a2197ab8a9b0.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{action-center-a932a39e29ac3489.js → action-center-a694e71d11bed653.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{activity-2cfdf4d55a7594ba.js → activity-312edbab3c17f26a.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{datamap-07881d1a5fc03d41.js → datamap-e8bfa1a3a8b84b6d.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/{[...subfieldNames]-57be9d40c67b0acb.js → [...subfieldNames]-f976632b92911072.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/{[collectionName]-bd78d6c6264e2467.js → [collectionName]-9ffa34d7ee7b2872.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/{[datasetId]-3c9103487b55e76f.js → [datasetId]-6e65dcdd692b4625.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/{new-e30a546a8cfb6658.js → new-423f08db5d9adc9a.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset-2bd2b941ad8f87b1.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{[id]-34958fe8183d9479.js → [id]-1b7bfb005fd8e4e1.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{new-761294dbaf59bbe1.js → new-b737165f7752f039.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{datastore-connection-59abd36059863e05.js → datastore-connection-6b02666ce735e092.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{index-ae100a873eb66d59.js → index-99ad22eddbb6b7f2.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-97f9e9b2822d2576.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/integrations-4ce156e73fe3608f.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{[id]-2aada2c7b9156053.js → [id]-8970d29f1710f486.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{add-template-fbb7b0c43dedf072.js → add-template-db905b79b189989c.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{messaging-7230d7ee21368cef.js → messaging-10084105bae43a19.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/{ant-components-7c234412502f8102.js → ant-components-cf7c0b3782c0c7a6.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{AntForm-72791aab60f3a4bf.js → AntForm-8cf5c6bb7f4595eb.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikAntFormItem-da7d11d6146fa746.js → FormikAntFormItem-01904c9c8521ef1c.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikControlled-3045d24344e99017.js → FormikControlled-ed8c23307b2b6868.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikField-5b5b165d3f41a1de.js → FormikField-3ec8e1811906a1d2.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/{forms-3afd8b6ba6234366.js → forms-18fc8b3a8ccfc80b.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/{table-migration-52d50286216bcb8c.js → table-migration-372166dc1d6268ea.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-104f33c424613732.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/{messaging-535b6e5003d892eb.js → messaging-a29479bc35b00f45.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/{storage-7ded688a1e832c63.js → storage-10e2886bc4d4f62b.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/{configure-08e0863d432b3348.js → configure-340150cac5bf8e4a.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-b1772281866cb827.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/properties/{[id]-b8dcb1f5213521ef.js → [id]-d9cdc82249593440.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/properties/{add-property-7d8418bb7cb9e1fd.js → add-property-d2e0236ab65b1fb9.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{properties-537003822f360ae7.js → properties-156bd0e36831ed04.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/reporting/{datamap-ac25749935da453b.js → datamap-49e5607055db1bee.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/about/{alpha-647d59bb0aa060bf.js → alpha-68697c49b290ba50.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/{about-73adc03fe0182e3f.js → about-a45a5b9f78c64e27.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent/[configuration_id]/{[purpose_id]-ffa9e9e79ad75828.js → [purpose_id]-c54d90dd4ac04de3.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/{consent-4fb6c8c4bd9cdb3f.js → consent-2ecf179f6587e3b3.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/{custom-fields-94c1b7bfc6cec4d2.js → custom-fields-80bf043deb37a20c.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domain-records-e9838b8e49e64e57.js → domain-records-c2ef327dc49618e9.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domains-0de16778ad2f8865.js → domains-bdc7ee59802c2e4a.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/{email-templates-aac71677024210ad.js → email-templates-6af619d1d57bb99c.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/{locations-f43e238571b21643.js → locations-09cb08245844c601.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/{organization-f5e0a34f6ae473ad.js → organization-d9e7feee568f6e35.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/{regulations-05d3c86ca3ca4d5d.js → regulations-7cfbb9149f96961a.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/{test-datasets-31fcf7b52d8028b0.js → test-datasets-9f5912cb2f471fdf.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/{[id]-6db01a1afe2f82d5.js → [id]-0252e5f648c5e3f8.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{systems-8ec7472a7032301f.js → systems-5332864c5e8595dc.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{taxonomy-84caae0fc02f8ae1.js → taxonomy-80f4ab8b7b6e7f5e.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/{[id]-e452541827698b1f.js → [id]-e607e07bd1ef2da0.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{user-management-530be849391d2425.js → user-management-d539f1c4e6adf73a.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/webpack-8fc1c717e1c0f7ae.js +1 -0
- fides/ui-build/static/admin/_next/static/css/5f8af79f94072e0f.css +1 -0
- fides/ui-build/static/admin/_next/static/hww-k841LVyuYWaSAg-CK/_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/images/connector-logos/manual_tasks.svg +25 -0
- 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-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/chunks/1169-ae67fde0c6d69abc.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/3450-4e472b9e2754fa47.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/4121-10bfa009892586fa.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/6662-d8ae12f69d325004.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/827-c6fe34fb336467ae.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset-500610c0b60f9e7e.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-8eee4d0314c83e50.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/integrations-bf3b87b0dd702551.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-00fb442c4adb7371.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-c8b02ae92dd7e45b.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/webpack-e25ccaae1ef867a2.js +0 -1
- fides/ui-build/static/admin/_next/static/css/23391a3311f80cfe.css +0 -1
- fides/ui-build/static/admin/_next/static/z7GzAZhoGiO521zm7WPYX/_buildManifest.js +0 -1
- {ethyca_fides-2.64.6b1.dist-info → ethyca_fides-2.65.0.dist-info}/WHEEL +0 -0
- {ethyca_fides-2.64.6b1.dist-info → ethyca_fides-2.65.0.dist-info}/entry_points.txt +0 -0
- {ethyca_fides-2.64.6b1.dist-info → ethyca_fides-2.65.0.dist-info}/licenses/LICENSE +0 -0
- {ethyca_fides-2.64.6b1.dist-info → ethyca_fides-2.65.0.dist-info}/top_level.txt +0 -0
- /fides/ui-build/static/admin/_next/static/{z7GzAZhoGiO521zm7WPYX → hww-k841LVyuYWaSAg-CK}/_ssgManifest.js +0 -0
fides/_version.py
CHANGED
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2025-07-
|
|
11
|
+
"date": "2025-07-08T13:15:47-0300",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "2.
|
|
14
|
+
"full-revisionid": "34ee2ee50c7518572e66a4441078263e59ba4030",
|
|
15
|
+
"version": "2.65.0"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""add user_id to manual_task_log
|
|
2
|
+
|
|
3
|
+
Revision ID: 641f6bcd424f
|
|
4
|
+
Revises: 41a634d8c669
|
|
5
|
+
Create Date: 2025-07-02 03:19:40.171201
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import sqlalchemy as sa
|
|
10
|
+
from alembic import op
|
|
11
|
+
|
|
12
|
+
# revision identifiers, used by Alembic.
|
|
13
|
+
revision = "641f6bcd424f"
|
|
14
|
+
down_revision = "41a634d8c669"
|
|
15
|
+
branch_labels = None
|
|
16
|
+
depends_on = None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def upgrade():
|
|
20
|
+
op.add_column("manual_task_log", sa.Column("user_id", sa.String(), nullable=True))
|
|
21
|
+
op.create_index(
|
|
22
|
+
op.f("ix_manual_task_log_user_id"), "manual_task_log", ["user_id"], unique=False
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def downgrade():
|
|
27
|
+
op.drop_index(op.f("ix_manual_task_log_user_id"), table_name="manual_task_log")
|
|
28
|
+
op.drop_column("manual_task_log", "user_id")
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
from functools import partial
|
|
1
2
|
from typing import Dict, List, Optional, Type, Union
|
|
2
3
|
|
|
3
4
|
from fastapi import Depends, HTTPException, Query, Response, Security
|
|
5
|
+
from fastapi.concurrency import run_in_threadpool
|
|
4
6
|
from fastapi.encoders import jsonable_encoder
|
|
5
7
|
from fastapi.responses import JSONResponse
|
|
6
8
|
from fastapi_pagination import Page, Params
|
|
@@ -224,9 +226,17 @@ async def list_dataset_paginated(
|
|
|
224
226
|
|
|
225
227
|
pagination_params = Params(page=page or 1, size=size or 50)
|
|
226
228
|
results = await async_paginate(db, filtered_query, pagination_params)
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
]
|
|
229
|
+
|
|
230
|
+
validated_items = []
|
|
231
|
+
for result in results.items: # type: ignore[attr-defined]
|
|
232
|
+
# run pydantic validation in a threadpool to avoid blocking the main thread
|
|
233
|
+
validated_item = await run_in_threadpool(
|
|
234
|
+
partial(DatasetResponse.model_validate, result.__dict__)
|
|
235
|
+
)
|
|
236
|
+
validated_items.append(validated_item)
|
|
237
|
+
|
|
238
|
+
results.items = validated_items # type: ignore[attr-defined]
|
|
239
|
+
|
|
230
240
|
return results
|
|
231
241
|
|
|
232
242
|
|
|
@@ -8,6 +8,7 @@ from fides.api.email_templates.template_names import (
|
|
|
8
8
|
CONSENT_REQUEST_EMAIL_FULFILLMENT,
|
|
9
9
|
CONSENT_REQUEST_VERIFICATION_TEMPLATE,
|
|
10
10
|
EMAIL_ERASURE_REQUEST_FULFILLMENT,
|
|
11
|
+
EXTERNAL_USER_WELCOME,
|
|
11
12
|
PRIVACY_REQUEST_COMPLETE_ACCESS_TEMPLATE,
|
|
12
13
|
PRIVACY_REQUEST_COMPLETE_DELETION_TEMPLATE,
|
|
13
14
|
PRIVACY_REQUEST_ERROR_NOTIFICATION_TEMPLATE,
|
|
@@ -29,7 +30,7 @@ template_env = Environment(
|
|
|
29
30
|
)
|
|
30
31
|
|
|
31
32
|
|
|
32
|
-
def get_email_template( # pylint: disable=too-many-return-statements
|
|
33
|
+
def get_email_template( # pylint: disable=too-many-return-statements, too-many-branches
|
|
33
34
|
action_type: MessagingActionType,
|
|
34
35
|
) -> Template:
|
|
35
36
|
if action_type == MessagingActionType.CONSENT_REQUEST:
|
|
@@ -56,6 +57,8 @@ def get_email_template( # pylint: disable=too-many-return-statements
|
|
|
56
57
|
return template_env.get_template(TEST_MESSAGE_TEMPLATE)
|
|
57
58
|
if action_type == MessagingActionType.USER_INVITE:
|
|
58
59
|
return template_env.get_template(USER_INVITE)
|
|
60
|
+
if action_type == MessagingActionType.EXTERNAL_USER_WELCOME:
|
|
61
|
+
return template_env.get_template(EXTERNAL_USER_WELCOME)
|
|
59
62
|
|
|
60
63
|
logger.error("No corresponding template linked to the {}", action_type)
|
|
61
64
|
raise EmailTemplateUnhandledActionType(
|
|
@@ -10,3 +10,4 @@ PRIVACY_REQUEST_REVIEW_DENY_TEMPLATE = "privacy_request_review_deny.html"
|
|
|
10
10
|
PRIVACY_REQUEST_REVIEW_APPROVE_TEMPLATE = "privacy_request_review_approve.html"
|
|
11
11
|
TEST_MESSAGE_TEMPLATE = "test_message.html"
|
|
12
12
|
USER_INVITE = "user_invite.html"
|
|
13
|
+
EXTERNAL_USER_WELCOME = "external_user_welcome.html"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>Welcome to Privacy Center</title>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<main>
|
|
9
|
+
<p>Hello {{ display_name }},</p>
|
|
10
|
+
|
|
11
|
+
<p>An account has been created for you by the privacy team at {{ org_name }} so that you can assist them in responding to data subject requests, as required by the GDPR and many US state laws, for users that have data in your systems.</p>
|
|
12
|
+
|
|
13
|
+
<p>A portal is available to view and take action on these requests at: <a href="{{ portal_link }}">{{ portal_link }}</a>. Through this portal you can upload or provide user data for users who have requested a copy of their information and attest that users have been removed from your system in the case of an erasure request.</p>
|
|
14
|
+
|
|
15
|
+
<p>The provided link is valid for 30 days and you will be asked to verify your email address each time you access the portal.</p>
|
|
16
|
+
|
|
17
|
+
<p>If you have any questions, please reach out first to your contacts at: {{ org_name }}</p>
|
|
18
|
+
|
|
19
|
+
<p>Regards,<br/>
|
|
20
|
+
{{ org_name }} Privacy Team</p>
|
|
21
|
+
</main>
|
|
22
|
+
</body>
|
|
23
|
+
</html>
|
|
@@ -19,16 +19,16 @@ CONFIG = get_config()
|
|
|
19
19
|
if TYPE_CHECKING:
|
|
20
20
|
from fides.api.models.fides_user import FidesUser
|
|
21
21
|
|
|
22
|
-
# Access links stay active for
|
|
22
|
+
# Access links stay active for 30 days for external login functionality. A new link is generated for each email.
|
|
23
23
|
# The emails are created for new DSRs which are assigned to the respondent.
|
|
24
|
-
ACCESS_LINK_TTL_DAYS =
|
|
24
|
+
ACCESS_LINK_TTL_DAYS = 30
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class FidesUserRespondentEmailVerification(Base, IdentityVerificationMixin):
|
|
28
28
|
"""Model for handling email verification for external respondents.
|
|
29
29
|
|
|
30
30
|
This handles two types of verification:
|
|
31
|
-
1. Access links - long-lived (
|
|
31
|
+
1. Access links - long-lived (30 days) for initial access
|
|
32
32
|
2. Verification codes - short-lived (1 hour) for actual verification
|
|
33
33
|
|
|
34
34
|
When an email is sent to an external respondent, a new verification is created with a new access token is created.
|
fides/api/models/manual_task.py
CHANGED
|
@@ -20,6 +20,7 @@ from sqlalchemy.sql import func
|
|
|
20
20
|
|
|
21
21
|
from fides.api.db.base_class import Base, FidesBase
|
|
22
22
|
from fides.api.db.util import EnumColumn
|
|
23
|
+
from fides.api.request_context import get_user_id
|
|
23
24
|
from fides.api.schemas.base_class import FidesSchema
|
|
24
25
|
|
|
25
26
|
if TYPE_CHECKING:
|
|
@@ -880,6 +881,10 @@ class ManualTaskLog(Base):
|
|
|
880
881
|
ForeignKey("manual_task_instance.id", ondelete="CASCADE"),
|
|
881
882
|
nullable=True,
|
|
882
883
|
)
|
|
884
|
+
# The user responsible for the action being logged. This may be `None`
|
|
885
|
+
# for system-initiated events or for legacy records created before this
|
|
886
|
+
# column existed.
|
|
887
|
+
user_id = Column(String, nullable=True, index=True)
|
|
883
888
|
status = Column(String, nullable=False)
|
|
884
889
|
message = Column(String, nullable=True)
|
|
885
890
|
details = Column(JSONB, nullable=True)
|
|
@@ -890,6 +895,7 @@ class ManualTaskLog(Base):
|
|
|
890
895
|
Index("ix_manual_task_log_instance_id", "instance_id"),
|
|
891
896
|
Index("ix_manual_task_log_status", "status"),
|
|
892
897
|
Index("ix_manual_task_log_task_id", "task_id"),
|
|
898
|
+
Index("ix_manual_task_log_user_id", "user_id"),
|
|
893
899
|
)
|
|
894
900
|
|
|
895
901
|
# Relationships
|
|
@@ -908,6 +914,7 @@ class ManualTaskLog(Base):
|
|
|
908
914
|
task_id: str,
|
|
909
915
|
status: "ManualTaskLogStatus",
|
|
910
916
|
message: str,
|
|
917
|
+
user_id: Optional[str] = None,
|
|
911
918
|
config_id: Optional[str] = None,
|
|
912
919
|
instance_id: Optional[str] = None,
|
|
913
920
|
details: Optional[dict[str, Any]] = None,
|
|
@@ -921,10 +928,12 @@ class ManualTaskLog(Base):
|
|
|
921
928
|
message: Optional message describing the event
|
|
922
929
|
details: Optional additional details about the event
|
|
923
930
|
"""
|
|
931
|
+
|
|
924
932
|
data = {
|
|
925
933
|
"task_id": task_id,
|
|
926
934
|
"config_id": config_id,
|
|
927
935
|
"instance_id": instance_id,
|
|
936
|
+
"user_id": user_id or get_user_id(),
|
|
928
937
|
"status": status,
|
|
929
938
|
"message": message,
|
|
930
939
|
"details": details,
|
|
@@ -937,6 +946,7 @@ class ManualTaskLog(Base):
|
|
|
937
946
|
db: Session,
|
|
938
947
|
task_id: str,
|
|
939
948
|
message: str,
|
|
949
|
+
user_id: Optional[str] = None,
|
|
940
950
|
config_id: Optional[str] = None,
|
|
941
951
|
instance_id: Optional[str] = None,
|
|
942
952
|
details: Optional[dict[str, Any]] = None,
|
|
@@ -954,12 +964,14 @@ class ManualTaskLog(Base):
|
|
|
954
964
|
Returns:
|
|
955
965
|
The created error log entry
|
|
956
966
|
"""
|
|
967
|
+
|
|
957
968
|
return cls.create_log(
|
|
958
969
|
db=db,
|
|
959
970
|
status=ManualTaskLogStatus.error,
|
|
960
971
|
task_id=task_id,
|
|
961
972
|
config_id=config_id,
|
|
962
973
|
instance_id=instance_id,
|
|
974
|
+
user_id=user_id or get_user_id(),
|
|
963
975
|
message=message,
|
|
964
976
|
details=details,
|
|
965
977
|
)
|
fides/api/oauth/utils.py
CHANGED
|
@@ -31,6 +31,7 @@ from fides.api.models.policy import PolicyPreWebhook
|
|
|
31
31
|
from fides.api.models.pre_approval_webhook import PreApprovalWebhook
|
|
32
32
|
from fides.api.models.privacy_request import RequestTask
|
|
33
33
|
from fides.api.oauth.roles import get_scopes_from_roles
|
|
34
|
+
from fides.api.request_context import set_user_id
|
|
34
35
|
from fides.api.schemas.external_https import RequestTaskJWE, WebhookJWE
|
|
35
36
|
from fides.api.schemas.oauth import OAuth2ClientCredentialsBearer
|
|
36
37
|
from fides.common.api.v1.urn_registry import TOKEN, V1_URL_PREFIX
|
|
@@ -325,6 +326,16 @@ def extract_token_and_load_client(
|
|
|
325
326
|
logger.debug("Auth token belongs to an invalid client_id.")
|
|
326
327
|
raise AuthorizationError(detail="Not Authorized for this action")
|
|
327
328
|
|
|
329
|
+
# Populate request-scoped context with the authenticated user identifier.
|
|
330
|
+
# Prefer the linked user_id; fall back to the client id when this is the
|
|
331
|
+
# special root client (which has no associated FidesUser row).
|
|
332
|
+
ctx_user_id = client.user_id
|
|
333
|
+
if not ctx_user_id and client.id == CONFIG.security.oauth_root_client_id:
|
|
334
|
+
ctx_user_id = CONFIG.security.oauth_root_client_id
|
|
335
|
+
|
|
336
|
+
if ctx_user_id:
|
|
337
|
+
set_user_id(ctx_user_id)
|
|
338
|
+
|
|
328
339
|
return token_data, client
|
|
329
340
|
|
|
330
341
|
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Utilities for storing and accessing request-scoped context that must be
|
|
3
|
+
accessible across the entire application stack (endpoints -> services ->
|
|
4
|
+
helpers -> decorators) without having to thread additional parameters through
|
|
5
|
+
all call-sites.
|
|
6
|
+
|
|
7
|
+
Currently we only capture the authenticated `user_id` but additional fields
|
|
8
|
+
(e.g. correlation_id, locale, feature_flags) can be added in the future by
|
|
9
|
+
expanding the `RequestContext` dataclass.
|
|
10
|
+
|
|
11
|
+
A `contextvars.ContextVar` is used instead of a module-level global to ensure
|
|
12
|
+
that values are local to the current execution context (async task, thread or
|
|
13
|
+
Celery worker) and therefore safe for concurrent workloads.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import contextvars
|
|
19
|
+
from dataclasses import dataclass
|
|
20
|
+
from typing import Any, Optional
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"get_user_id",
|
|
24
|
+
"set_user_id",
|
|
25
|
+
"reset_request_context",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass
|
|
30
|
+
class RequestContext:
|
|
31
|
+
user_id: Optional[str] = None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# A single ContextVar holding the current request context.
|
|
35
|
+
_ctx: contextvars.ContextVar[RequestContext] = contextvars.ContextVar(
|
|
36
|
+
"request_context",
|
|
37
|
+
default=RequestContext(),
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def get_request_context() -> RequestContext:
|
|
42
|
+
"""Return the current `RequestContext` for this request.
|
|
43
|
+
|
|
44
|
+
- The context is populated during authentication by `extract_token_and_load_client()`,
|
|
45
|
+
which calls `fides.api.request_context.set_request_context` with
|
|
46
|
+
the authenticated `user_id`.
|
|
47
|
+
- A `ContextVar` keeps the data isolated per request. Each coroutine
|
|
48
|
+
or thread sees its own copy and it is discarded at the end of the request.
|
|
49
|
+
- The returned object is the live context; treat it as read-only and use
|
|
50
|
+
`set_request_context` to mutate values.
|
|
51
|
+
"""
|
|
52
|
+
return _ctx.get()
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def set_request_context(**kwargs: Any) -> None:
|
|
56
|
+
"""Mutate the current context in place using `key=value` pairs."""
|
|
57
|
+
ctx = _ctx.get()
|
|
58
|
+
for key, value in kwargs.items():
|
|
59
|
+
if hasattr(ctx, key):
|
|
60
|
+
setattr(ctx, key, value)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def reset_request_context() -> None:
|
|
64
|
+
"""Remove all context, mainly for test clean-up."""
|
|
65
|
+
_ctx.set(RequestContext())
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def get_user_id() -> Optional[str]:
|
|
69
|
+
"""Return the user_id from the current request context."""
|
|
70
|
+
ctx = get_request_context()
|
|
71
|
+
return ctx.user_id
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def set_user_id(user_id: str) -> None:
|
|
75
|
+
"""Set the user_id in the current request context."""
|
|
76
|
+
set_request_context(user_id=user_id)
|
|
@@ -69,6 +69,7 @@ class MessagingActionType(str, Enum):
|
|
|
69
69
|
PRIVACY_REQUEST_REVIEW_DENY = "privacy_request_review_deny"
|
|
70
70
|
PRIVACY_REQUEST_REVIEW_APPROVE = "privacy_request_review_approve"
|
|
71
71
|
USER_INVITE = "user_invite"
|
|
72
|
+
EXTERNAL_USER_WELCOME = "external_user_welcome"
|
|
72
73
|
TEST_MESSAGE = "test_message"
|
|
73
74
|
|
|
74
75
|
|
|
@@ -182,6 +183,17 @@ class UserInviteBodyParams(BaseModel):
|
|
|
182
183
|
invite_code: str
|
|
183
184
|
|
|
184
185
|
|
|
186
|
+
class ExternalUserWelcomeBodyParams(BaseModel):
|
|
187
|
+
"""Body params required to send a welcome email to external users"""
|
|
188
|
+
|
|
189
|
+
username: str
|
|
190
|
+
first_name: Optional[str] = None
|
|
191
|
+
last_name: Optional[str] = None
|
|
192
|
+
privacy_center_url: str
|
|
193
|
+
access_token: str
|
|
194
|
+
org_name: str
|
|
195
|
+
|
|
196
|
+
|
|
185
197
|
class FidesopsMessage(
|
|
186
198
|
BaseModel,
|
|
187
199
|
):
|
|
@@ -198,6 +210,7 @@ class FidesopsMessage(
|
|
|
198
210
|
ErasureRequestBodyParams,
|
|
199
211
|
ErrorNotificationBodyParams,
|
|
200
212
|
UserInviteBodyParams,
|
|
213
|
+
ExternalUserWelcomeBodyParams,
|
|
201
214
|
]
|
|
202
215
|
] = None
|
|
203
216
|
|
|
@@ -217,6 +230,7 @@ class FidesopsMessage(
|
|
|
217
230
|
MessagingActionType.MESSAGE_ERASURE_REQUEST_FULFILLMENT: ErasureRequestBodyParams,
|
|
218
231
|
MessagingActionType.PRIVACY_REQUEST_ERROR_NOTIFICATION: ErrorNotificationBodyParams,
|
|
219
232
|
MessagingActionType.USER_INVITE: UserInviteBodyParams,
|
|
233
|
+
MessagingActionType.EXTERNAL_USER_WELCOME: ExternalUserWelcomeBodyParams,
|
|
220
234
|
}
|
|
221
235
|
|
|
222
236
|
valid_body_params = valid_body_params_for_action_type.get(
|
|
@@ -30,6 +30,12 @@ class FilterPostProcessorConfiguration(StrategyConfiguration):
|
|
|
30
30
|
case_sensitive: bool = True
|
|
31
31
|
|
|
32
32
|
|
|
33
|
+
class ExtractForExecutionLogPostProcessorConfiguration(StrategyConfiguration):
|
|
34
|
+
"""Configuration for extracting data from response body and adding to execution log messages"""
|
|
35
|
+
|
|
36
|
+
path: Optional[str] = None
|
|
37
|
+
|
|
38
|
+
|
|
33
39
|
class OffsetPaginationConfiguration(StrategyConfiguration):
|
|
34
40
|
"""
|
|
35
41
|
Increases the value of the query param `incremental_param` by the `increment_by` until the `limit` is hit
|
|
@@ -423,6 +423,7 @@ class SaaSConnector(BaseConnector[AuthenticatedClient], Contextualizable):
|
|
|
423
423
|
response_data,
|
|
424
424
|
identity_data,
|
|
425
425
|
cast(Optional[List[PostProcessorStrategy]], saas_request.postprocessors),
|
|
426
|
+
response,
|
|
426
427
|
)
|
|
427
428
|
|
|
428
429
|
logger.info(
|
|
@@ -456,6 +457,7 @@ class SaaSConnector(BaseConnector[AuthenticatedClient], Contextualizable):
|
|
|
456
457
|
response_data: Union[List[Dict[str, Any]], Dict[str, Any]],
|
|
457
458
|
identity_data: Dict[str, Any],
|
|
458
459
|
postprocessors: Optional[List[PostProcessorStrategy]],
|
|
460
|
+
response: Optional[Response] = None,
|
|
459
461
|
) -> List[Row]:
|
|
460
462
|
"""
|
|
461
463
|
Runs the raw response through all available postprocessors for the request,
|
|
@@ -481,7 +483,9 @@ class SaaSConnector(BaseConnector[AuthenticatedClient], Contextualizable):
|
|
|
481
483
|
processed_data,
|
|
482
484
|
identity_data,
|
|
483
485
|
privacy_request,
|
|
486
|
+
response,
|
|
484
487
|
)
|
|
488
|
+
|
|
485
489
|
except Exception as exc:
|
|
486
490
|
raise PostProcessingException(
|
|
487
491
|
f"Exception occurred during the '{postprocessor.strategy}' postprocessor " # type: ignore
|
|
@@ -567,6 +571,7 @@ class SaaSConnector(BaseConnector[AuthenticatedClient], Contextualizable):
|
|
|
567
571
|
rows,
|
|
568
572
|
privacy_request.get_cached_identity_data(),
|
|
569
573
|
cast(Optional[List[PostProcessorStrategy]], masking_request.postprocessors),
|
|
574
|
+
None,
|
|
570
575
|
)
|
|
571
576
|
|
|
572
577
|
client = self.create_client()
|
|
@@ -584,9 +589,46 @@ class SaaSConnector(BaseConnector[AuthenticatedClient], Contextualizable):
|
|
|
584
589
|
)
|
|
585
590
|
continue
|
|
586
591
|
raise exc
|
|
587
|
-
client.send(prepared_request, masking_request.ignore_errors)
|
|
592
|
+
response = client.send(prepared_request, masking_request.ignore_errors)
|
|
588
593
|
rows_updated += 1
|
|
589
594
|
|
|
595
|
+
# Run post-processors against the response from the masking request so that
|
|
596
|
+
# processors such as `extract_for_execution_log` can inspect the API
|
|
597
|
+
# response body (e.g. confirmation, ticket IDs, etc.). We ignore the
|
|
598
|
+
# returned rows because masking responses are not used downstream.
|
|
599
|
+
try:
|
|
600
|
+
handled_response = self._handle_errored_response(
|
|
601
|
+
masking_request, response
|
|
602
|
+
)
|
|
603
|
+
response_data = self._unwrap_response_data(
|
|
604
|
+
masking_request, handled_response
|
|
605
|
+
)
|
|
606
|
+
|
|
607
|
+
# Only attempt post-processing if we have post-processors and the response body
|
|
608
|
+
# is JSON-serializable (dict or list of dicts).
|
|
609
|
+
if masking_request.postprocessors and isinstance(
|
|
610
|
+
response_data, (dict, list)
|
|
611
|
+
):
|
|
612
|
+
self.process_response_data(
|
|
613
|
+
response_data,
|
|
614
|
+
privacy_request.get_cached_identity_data(),
|
|
615
|
+
cast(
|
|
616
|
+
Optional[List[PostProcessorStrategy]],
|
|
617
|
+
masking_request.postprocessors,
|
|
618
|
+
),
|
|
619
|
+
handled_response,
|
|
620
|
+
)
|
|
621
|
+
except (
|
|
622
|
+
PostProcessingException,
|
|
623
|
+
Exception,
|
|
624
|
+
) as exc: # pylint: disable=broad-except
|
|
625
|
+
# We do not want a post-processing failure to prevent the masking
|
|
626
|
+
# operation itself from succeeding.
|
|
627
|
+
logger.warning(
|
|
628
|
+
"Post-processing of masking request response failed: {}",
|
|
629
|
+
exc,
|
|
630
|
+
)
|
|
631
|
+
|
|
590
632
|
self.unset_connector_state()
|
|
591
633
|
|
|
592
634
|
awaiting_async_callback: bool = bool(
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Execution context for collecting log messages during privacy request processing.
|
|
3
|
+
|
|
4
|
+
Uses Python's contextvars for thread-safe, execution-scoped message collection.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import contextvars
|
|
8
|
+
from contextlib import contextmanager
|
|
9
|
+
from typing import Generator, List, Optional
|
|
10
|
+
|
|
11
|
+
from loguru import logger
|
|
12
|
+
|
|
13
|
+
# Context variable for current execution messages
|
|
14
|
+
_execution_messages: contextvars.ContextVar[Optional[List[str]]] = (
|
|
15
|
+
contextvars.ContextVar("execution_messages")
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@contextmanager
|
|
20
|
+
def collect_execution_log_messages() -> Generator[List[str], None, None]:
|
|
21
|
+
"""
|
|
22
|
+
Context manager for collecting execution log messages.
|
|
23
|
+
|
|
24
|
+
Usage:
|
|
25
|
+
with collect_execution_log_messages() as messages:
|
|
26
|
+
# ... do work that calls add_execution_log_message()
|
|
27
|
+
pass
|
|
28
|
+
# messages now contains all collected messages
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
List[str]: Messages collected during execution
|
|
32
|
+
"""
|
|
33
|
+
messages: List[str] = []
|
|
34
|
+
token = _execution_messages.set(messages)
|
|
35
|
+
try:
|
|
36
|
+
yield messages
|
|
37
|
+
finally:
|
|
38
|
+
_execution_messages.reset(token)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def add_execution_log_message(message: str) -> None:
|
|
42
|
+
"""Add a message to the current execution context"""
|
|
43
|
+
try:
|
|
44
|
+
messages = _execution_messages.get()
|
|
45
|
+
if messages is not None and message.strip():
|
|
46
|
+
messages.append(message.strip())
|
|
47
|
+
except LookupError:
|
|
48
|
+
logger.error(
|
|
49
|
+
f"Attempted to call add_execution_log_message outside of execution context, unable to add message: {message}"
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def get_execution_log_messages() -> List[str]:
|
|
54
|
+
"""Get messages from current execution context (for testing/debugging)"""
|
|
55
|
+
try:
|
|
56
|
+
messages = _execution_messages.get()
|
|
57
|
+
return messages.copy() if messages is not None else []
|
|
58
|
+
except LookupError:
|
|
59
|
+
return []
|
|
@@ -26,6 +26,7 @@ from fides.api.schemas.messaging.messaging import (
|
|
|
26
26
|
EmailForActionType,
|
|
27
27
|
ErasureRequestBodyParams,
|
|
28
28
|
ErrorNotificationBodyParams,
|
|
29
|
+
ExternalUserWelcomeBodyParams,
|
|
29
30
|
FidesopsMessage,
|
|
30
31
|
MessagingActionType,
|
|
31
32
|
MessagingMethod,
|
|
@@ -176,6 +177,7 @@ def dispatch_message(
|
|
|
176
177
|
ErasureRequestBodyParams,
|
|
177
178
|
UserInviteBodyParams,
|
|
178
179
|
ErrorNotificationBodyParams,
|
|
180
|
+
ExternalUserWelcomeBodyParams,
|
|
179
181
|
]
|
|
180
182
|
] = None,
|
|
181
183
|
subject_override: Optional[str] = None,
|
|
@@ -351,7 +353,7 @@ def _render(template_str: str, variables: Optional[Dict] = None) -> str:
|
|
|
351
353
|
return template_str
|
|
352
354
|
|
|
353
355
|
|
|
354
|
-
def _build_email( # pylint: disable=too-many-return-statements
|
|
356
|
+
def _build_email( # pylint: disable=too-many-return-statements, too-many-branches
|
|
355
357
|
config_proxy: ConfigProxy,
|
|
356
358
|
action_type: MessagingActionType,
|
|
357
359
|
body_params: Any,
|
|
@@ -463,6 +465,36 @@ def _build_email( # pylint: disable=too-many-return-statements
|
|
|
463
465
|
}
|
|
464
466
|
),
|
|
465
467
|
)
|
|
468
|
+
if action_type == MessagingActionType.EXTERNAL_USER_WELCOME:
|
|
469
|
+
base_template = get_email_template(action_type)
|
|
470
|
+
# Generate display name for personalization
|
|
471
|
+
display_name = body_params.username
|
|
472
|
+
if body_params.first_name:
|
|
473
|
+
display_name = body_params.first_name
|
|
474
|
+
if body_params.last_name:
|
|
475
|
+
display_name = f"{body_params.first_name} {body_params.last_name}"
|
|
476
|
+
|
|
477
|
+
portal_link = (
|
|
478
|
+
f"{body_params.privacy_center_url}?access_token={body_params.access_token}"
|
|
479
|
+
)
|
|
480
|
+
|
|
481
|
+
variables = {
|
|
482
|
+
"username": body_params.username,
|
|
483
|
+
"display_name": display_name,
|
|
484
|
+
"first_name": body_params.first_name,
|
|
485
|
+
"last_name": body_params.last_name,
|
|
486
|
+
"org_name": body_params.org_name,
|
|
487
|
+
"portal_link": portal_link,
|
|
488
|
+
"privacy_center_url": body_params.privacy_center_url,
|
|
489
|
+
"access_token": body_params.access_token,
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
return EmailForActionType(
|
|
493
|
+
subject="Welcome to our Privacy Center",
|
|
494
|
+
body=base_template.render(variables),
|
|
495
|
+
template_variables=variables,
|
|
496
|
+
)
|
|
497
|
+
|
|
466
498
|
logger.error("Message action type {} is not implemented", action_type)
|
|
467
499
|
raise MessageDispatchException(
|
|
468
500
|
f"Message action type {action_type} is not implemented"
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from abc import abstractmethod
|
|
2
2
|
from typing import Any, Dict, List, Optional, Union
|
|
3
3
|
|
|
4
|
+
from requests import Response
|
|
5
|
+
|
|
4
6
|
from fides.api.models.privacy_request import PrivacyRequest
|
|
5
7
|
from fides.api.service.strategy import Strategy
|
|
6
8
|
|
|
@@ -14,5 +16,13 @@ class PostProcessorStrategy(Strategy):
|
|
|
14
16
|
data: Any,
|
|
15
17
|
identity_data: Optional[Dict[str, Any]] = None,
|
|
16
18
|
privacy_request: Optional[PrivacyRequest] = None,
|
|
19
|
+
response: Optional[Response] = None,
|
|
17
20
|
) -> Union[List[Dict[str, Any]], Dict[str, Any]]:
|
|
18
|
-
"""Process data from SaaS connector
|
|
21
|
+
"""Process data from SaaS connector
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
data: The response data (potentially unwrapped/processed)
|
|
25
|
+
identity_data: Cached identity data for the request
|
|
26
|
+
privacy_request: The privacy request object
|
|
27
|
+
response: The raw HTTP response object (includes headers, status, etc.)
|
|
28
|
+
"""
|