ethyca-fides 2.64.6b2__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.6b2.dist-info → ethyca_fides-2.65.0.dist-info}/METADATA +1 -1
- {ethyca_fides-2.64.6b2.dist-info → ethyca_fides-2.65.0.dist-info}/RECORD +216 -212
- 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/models/manual_task.py +12 -0
- fides/api/oauth/utils.py +11 -0
- fides/api/request_context.py +76 -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/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/onw4yQbMe2hBVwh4fBpNY/_buildManifest.js +0 -1
- {ethyca_fides-2.64.6b2.dist-info → ethyca_fides-2.65.0.dist-info}/WHEEL +0 -0
- {ethyca_fides-2.64.6b2.dist-info → ethyca_fides-2.65.0.dist-info}/entry_points.txt +0 -0
- {ethyca_fides-2.64.6b2.dist-info → ethyca_fides-2.65.0.dist-info}/licenses/LICENSE +0 -0
- {ethyca_fides-2.64.6b2.dist-info → ethyca_fides-2.65.0.dist-info}/top_level.txt +0 -0
- /fides/ui-build/static/admin/_next/static/{onw4yQbMe2hBVwh4fBpNY → 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
|
|
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)
|
|
@@ -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 []
|
|
@@ -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
|
+
"""
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
from typing import Any, Dict, List, Optional, Union
|
|
2
|
+
|
|
3
|
+
import pydash
|
|
4
|
+
from loguru import logger
|
|
5
|
+
from requests import Response
|
|
6
|
+
|
|
7
|
+
from fides.api.models.privacy_request import PrivacyRequest
|
|
8
|
+
from fides.api.schemas.saas.strategy_configuration import (
|
|
9
|
+
ExtractForExecutionLogPostProcessorConfiguration,
|
|
10
|
+
)
|
|
11
|
+
from fides.api.service.execution_context import add_execution_log_message
|
|
12
|
+
from fides.api.service.processors.post_processor_strategy.post_processor_strategy import (
|
|
13
|
+
PostProcessorStrategy,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ExtractForExecutionLogPostProcessorStrategy(PostProcessorStrategy):
|
|
18
|
+
"""Postprocessor that extracts data from API response contents and adds it to execution log messages"""
|
|
19
|
+
|
|
20
|
+
name = "extract_for_execution_log"
|
|
21
|
+
configuration_model = ExtractForExecutionLogPostProcessorConfiguration
|
|
22
|
+
|
|
23
|
+
def __init__(self, configuration: ExtractForExecutionLogPostProcessorConfiguration):
|
|
24
|
+
self.configuration = configuration
|
|
25
|
+
|
|
26
|
+
def process(
|
|
27
|
+
self,
|
|
28
|
+
data: Union[List[Dict[str, Any]], Dict[str, Any]],
|
|
29
|
+
identity_data: Optional[Dict[str, Any]] = None,
|
|
30
|
+
privacy_request: Optional[PrivacyRequest] = None,
|
|
31
|
+
response: Optional[Response] = None,
|
|
32
|
+
) -> Union[List[Dict[str, Any]], Dict[str, Any]]:
|
|
33
|
+
"""
|
|
34
|
+
Extract data from response contents and add to execution log messages.
|
|
35
|
+
Data is passed through unchanged (non-destructive postprocessor).
|
|
36
|
+
"""
|
|
37
|
+
config = self.configuration
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
# Only process if response.contents is available
|
|
41
|
+
if response is None or not response.content:
|
|
42
|
+
return data
|
|
43
|
+
|
|
44
|
+
if config.path is None:
|
|
45
|
+
# No path specified - use entire response contents as string
|
|
46
|
+
message = str(response.content)
|
|
47
|
+
else:
|
|
48
|
+
# Attempt to parse the response content as JSON before extracting
|
|
49
|
+
try:
|
|
50
|
+
json_data: Any = response.json()
|
|
51
|
+
except ValueError:
|
|
52
|
+
logger.debug(
|
|
53
|
+
"Unable to parse response content as JSON for path extraction"
|
|
54
|
+
)
|
|
55
|
+
return data
|
|
56
|
+
|
|
57
|
+
extracted_value = pydash.get(json_data, config.path)
|
|
58
|
+
if extracted_value is None:
|
|
59
|
+
logger.debug(f"No data found at path '{config.path}'")
|
|
60
|
+
return data
|
|
61
|
+
|
|
62
|
+
message = str(extracted_value)
|
|
63
|
+
|
|
64
|
+
# Add message to execution context
|
|
65
|
+
add_execution_log_message(message)
|
|
66
|
+
logger.info(message)
|
|
67
|
+
|
|
68
|
+
except Exception as e:
|
|
69
|
+
error_msg = f"Error in extract_for_execution_log postprocessor: {e}"
|
|
70
|
+
logger.error(error_msg)
|
|
71
|
+
add_execution_log_message(error_msg)
|
|
72
|
+
|
|
73
|
+
return data
|
|
@@ -9,6 +9,9 @@ from fides.api.schemas.saas.strategy_configuration import StrategyConfiguration
|
|
|
9
9
|
from fides.api.service.processors.post_processor_strategy.post_processor_strategy import (
|
|
10
10
|
PostProcessorStrategy,
|
|
11
11
|
)
|
|
12
|
+
from fides.api.service.processors.post_processor_strategy.post_processor_strategy_extract_for_execution_log import (
|
|
13
|
+
ExtractForExecutionLogPostProcessorStrategy,
|
|
14
|
+
)
|
|
12
15
|
from fides.api.service.processors.post_processor_strategy.post_processor_strategy_filter import (
|
|
13
16
|
FilterPostProcessorStrategy,
|
|
14
17
|
)
|
|
@@ -24,6 +27,7 @@ class SupportedPostProcessorStrategies(Enum):
|
|
|
24
27
|
|
|
25
28
|
unwrap = UnwrapPostProcessorStrategy
|
|
26
29
|
filter = FilterPostProcessorStrategy
|
|
30
|
+
extract_for_execution_log = ExtractForExecutionLogPostProcessorStrategy
|
|
27
31
|
|
|
28
32
|
@classmethod
|
|
29
33
|
def __contains__(cls, item: str) -> bool:
|
|
@@ -2,6 +2,7 @@ from typing import Any, Dict, List, Optional, Union
|
|
|
2
2
|
|
|
3
3
|
import pydash
|
|
4
4
|
from loguru import logger
|
|
5
|
+
from requests import Response
|
|
5
6
|
|
|
6
7
|
from fides.api.common_exceptions import FidesopsException
|
|
7
8
|
from fides.api.models.privacy_request import PrivacyRequest
|
|
@@ -54,6 +55,7 @@ class FilterPostProcessorStrategy(PostProcessorStrategy):
|
|
|
54
55
|
data: Union[List[Dict[str, Any]], Dict[str, Any]],
|
|
55
56
|
identity_data: Optional[Dict[str, Any]] = None,
|
|
56
57
|
privacy_request: Optional[PrivacyRequest] = None,
|
|
58
|
+
response: Optional[Response] = None,
|
|
57
59
|
) -> Union[List[Dict[str, Any]], Dict[str, Any]]:
|
|
58
60
|
"""
|
|
59
61
|
- data: A list or a dict
|
|
@@ -2,6 +2,7 @@ from typing import Any, Dict, List, Optional, Union
|
|
|
2
2
|
|
|
3
3
|
import pydash
|
|
4
4
|
from loguru import logger
|
|
5
|
+
from requests import Response
|
|
5
6
|
|
|
6
7
|
from fides.api.models.privacy_request import PrivacyRequest
|
|
7
8
|
from fides.api.schemas.saas.strategy_configuration import (
|
|
@@ -44,6 +45,7 @@ class UnwrapPostProcessorStrategy(PostProcessorStrategy):
|
|
|
44
45
|
data: Union[List[Dict[str, Any]], Dict[str, Any]],
|
|
45
46
|
identity_data: Optional[Dict[str, Any]] = None,
|
|
46
47
|
privacy_request: Optional[PrivacyRequest] = None,
|
|
48
|
+
response: Optional[Response] = None,
|
|
47
49
|
) -> Union[List[Dict[str, Any]], Dict[str, Any]]:
|
|
48
50
|
"""
|
|
49
51
|
:param data: A list or dict
|
fides/api/task/graph_task.py
CHANGED
|
@@ -42,6 +42,7 @@ from fides.api.models.privacy_request import ExecutionLog, PrivacyRequest, Reque
|
|
|
42
42
|
from fides.api.models.worker_task import ExecutionLogStatus
|
|
43
43
|
from fides.api.schemas.policy import ActionType, CurrentStep
|
|
44
44
|
from fides.api.service.connectors.base_connector import BaseConnector
|
|
45
|
+
from fides.api.service.execution_context import collect_execution_log_messages
|
|
45
46
|
from fides.api.task.consolidate_query_matches import consolidate_query_matches
|
|
46
47
|
from fides.api.task.filter_element_match import filter_element_match
|
|
47
48
|
from fides.api.task.refine_target_path import FieldPathNodeInput
|
|
@@ -419,7 +420,7 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
|
|
|
419
420
|
self,
|
|
420
421
|
action_type: ActionType,
|
|
421
422
|
ex: Optional[BaseException] = None,
|
|
422
|
-
success_override_msg: Optional[
|
|
423
|
+
success_override_msg: Optional[str] = None,
|
|
423
424
|
) -> None:
|
|
424
425
|
"""On completion activities"""
|
|
425
426
|
if ex:
|
|
@@ -615,19 +616,29 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
|
|
|
615
616
|
formatted_input_data: NodeInput = self.pre_process_input_data(
|
|
616
617
|
*inputs, group_dependent_fields=True
|
|
617
618
|
)
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
self.
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
619
|
+
|
|
620
|
+
# Use execution context to capture postprocessor messages
|
|
621
|
+
with collect_execution_log_messages() as messages:
|
|
622
|
+
output: List[Row] = self.connector.retrieve_data(
|
|
623
|
+
self.execution_node,
|
|
624
|
+
self.resources.policy,
|
|
625
|
+
self.resources.request,
|
|
626
|
+
self.resources.privacy_request_task,
|
|
627
|
+
formatted_input_data,
|
|
628
|
+
)
|
|
629
|
+
|
|
625
630
|
filtered_output: List[Row] = self.access_results_post_processing(
|
|
626
631
|
self.pre_process_input_data(*inputs, group_dependent_fields=False),
|
|
627
632
|
output,
|
|
628
633
|
)
|
|
629
|
-
|
|
630
|
-
|
|
634
|
+
|
|
635
|
+
# Include postprocessor messages in success message if available
|
|
636
|
+
success_message = None
|
|
637
|
+
if messages:
|
|
638
|
+
success_message = "\n".join(messages)
|
|
639
|
+
|
|
640
|
+
self.log_end(ActionType.access, success_override_msg=success_message)
|
|
641
|
+
return filtered_output
|
|
631
642
|
|
|
632
643
|
@retry(action_type=ActionType.erasure, default_return=0)
|
|
633
644
|
def erasure_request(
|
|
@@ -683,13 +694,16 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
|
|
|
683
694
|
)
|
|
684
695
|
return 0
|
|
685
696
|
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
self.
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
697
|
+
# Use execution context to capture postprocessor messages
|
|
698
|
+
with collect_execution_log_messages() as messages:
|
|
699
|
+
output = self.connector.mask_data(
|
|
700
|
+
self.execution_node,
|
|
701
|
+
self.resources.policy,
|
|
702
|
+
self.resources.request,
|
|
703
|
+
self.resources.privacy_request_task,
|
|
704
|
+
retrieved_data,
|
|
705
|
+
)
|
|
706
|
+
|
|
693
707
|
if self.request_task.id:
|
|
694
708
|
# For DSR 3.0, largely for testing. DSR 3.0 uses Request Task status
|
|
695
709
|
# instead of presence of cached erasure data to know if we should rerun a node
|
|
@@ -700,7 +714,13 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
|
|
|
700
714
|
self.resources.cache_erasure(
|
|
701
715
|
self.key.value, output
|
|
702
716
|
) # Cache that the erasure was performed in case we need to restart
|
|
703
|
-
|
|
717
|
+
|
|
718
|
+
# Include postprocessor messages in success message if available
|
|
719
|
+
success_message = None
|
|
720
|
+
if messages:
|
|
721
|
+
success_message = "\n".join(messages)
|
|
722
|
+
|
|
723
|
+
self.log_end(ActionType.erasure, success_override_msg=success_message)
|
|
704
724
|
return output
|
|
705
725
|
|
|
706
726
|
@retry(action_type=ActionType.consent, default_return=False)
|