ethyca-fides 2.57.1b6__py2.py3-none-any.whl → 2.57.1b8__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ethyca_fides-2.57.1b6.dist-info → ethyca_fides-2.57.1b8.dist-info}/METADATA +1 -1
- {ethyca_fides-2.57.1b6.dist-info → ethyca_fides-2.57.1b8.dist-info}/RECORD +199 -198
- fides/_version.py +3 -3
- fides/api/api/v1/endpoints/config_endpoints.py +4 -2
- fides/api/api/v1/endpoints/generic_overrides.py +43 -6
- fides/api/main.py +4 -1
- fides/api/models/attachment.py +6 -8
- fides/api/models/comment.py +17 -17
- fides/api/models/connectionconfig.py +1 -1
- fides/api/models/privacy_request/privacy_request.py +61 -0
- fides/api/oauth/utils.py +11 -11
- fides/api/schemas/dataset.py +22 -2
- fides/api/service/privacy_request/request_runner_service.py +8 -4
- fides/api/service/storage/s3.py +133 -0
- fides/api/service/storage/util.py +10 -0
- fides/api/tasks/__init__.py +3 -1
- fides/api/tasks/storage.py +12 -111
- fides/config/__init__.py +1 -1
- fides/ui-build/static/admin/404.html +1 -1
- fides/ui-build/static/admin/_next/static/chunks/1376-c177d8d0c60b1166.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/3320-317483e6c10bae51.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/355-6a87b50acf54e985.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/3662-6a0cafa3023aa7a2.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/4723-1a785d558dfb6441.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/605-c782df008a0ff167.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/6362-72451aeb32815d26.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/6954-f7daf613febc36ef.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/7434-3d4a0beb84ec57f7.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/7495-2f5c8dfba2eabb4f.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/7958-d2bc63e1be612f36.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/7980-91800d54c5964ba3.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/{_app-de85703aa2346f42.js → _app-e53d13729068a001.js} +8 -8
- fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{manual-05ab19822a7e9f80.js → manual-5593bb1b6de0473d.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{multiple-18b0b521255289a3.js → multiple-6a7208eee5e588fb.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/add-systems-a33f82e79cb09478.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure/{add-vendors-64f83e9a2b777bf3.js → add-vendors-ba0c5fa9764cbd89.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/{configure-e11ace4f273ebb47.js → configure-1af99ffa7a507e86.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{[id]-443e6dd191ce5588.js → [id]-c02510104f9e503a.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{new-36162d5bea29dcc2.js → new-e96415629f3b4223.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{[id]-2d651499c07d12d9.js → [id]-66827da90b8a2d1e.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{new-36e57d2f2446be82.js → new-13d48f980bf707e5.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog-1a3bb713fc7bc298.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-5892ca5d93ea6165.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-4fac7e0a54eebc32.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/new-45016545c099e183.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset-5ddd3cd7d29e89c0.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{[id]-0616437e1a82d3ed.js → [id]-9bb953098f68f1ee.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{new-f8218440494e8532.js → new-cdcf42d4cb24b45a.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-108945832a7edd7d.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/integrations-e96e959d10afebea.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/messaging-5a161e167c251519.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-c3e234ad95e6e213.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-347e203faa31716f.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-729fa8ed0f10bc8e.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-ff6edba56dfec090.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/domains-ad368857e86fe01b.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/organization-f45920358a405167.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/{[id]-ca753b60ca1745c5.js → [id]-44f7fbfee9cf9267.js} +1 -1
- fides/ui-build/static/admin/_next/static/css/dd9922a434d21e22.css +1 -0
- fides/ui-build/static/admin/_next/static/lO31cDp9wEzsNdiUnl8It/_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/ant-poc.html +1 -1
- fides/ui-build/static/admin/consent/configure/add-vendors.html +1 -1
- fides/ui-build/static/admin/consent/configure.html +1 -1
- fides/ui-build/static/admin/consent/privacy-experience/[id].html +1 -1
- fides/ui-build/static/admin/consent/privacy-experience/new.html +1 -1
- fides/ui-build/static/admin/consent/privacy-experience.html +1 -1
- fides/ui-build/static/admin/consent/privacy-notices/[id].html +1 -1
- fides/ui-build/static/admin/consent/privacy-notices/new.html +1 -1
- fides/ui-build/static/admin/consent/privacy-notices.html +1 -1
- fides/ui-build/static/admin/consent/properties.html +1 -1
- fides/ui-build/static/admin/consent/reporting.html +1 -1
- fides/ui-build/static/admin/consent.html +1 -1
- fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn].html +1 -1
- fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn].html +1 -1
- fides/ui-build/static/admin/data-catalog/[systemId]/projects.html +1 -1
- fides/ui-build/static/admin/data-catalog/[systemId]/resources/[resourceUrn].html +1 -1
- fides/ui-build/static/admin/data-catalog/[systemId]/resources.html +1 -1
- fides/ui-build/static/admin/data-catalog.html +1 -1
- fides/ui-build/static/admin/data-discovery/action-center/[monitorId]/[systemId].html +1 -1
- fides/ui-build/static/admin/data-discovery/action-center/[monitorId].html +1 -1
- fides/ui-build/static/admin/data-discovery/action-center.html +1 -1
- fides/ui-build/static/admin/data-discovery/activity.html +1 -1
- fides/ui-build/static/admin/data-discovery/detection/[resourceUrn].html +1 -1
- fides/ui-build/static/admin/data-discovery/detection.html +1 -1
- fides/ui-build/static/admin/data-discovery/discovery/[resourceUrn].html +1 -1
- fides/ui-build/static/admin/data-discovery/discovery.html +1 -1
- fides/ui-build/static/admin/datamap.html +1 -1
- fides/ui-build/static/admin/dataset/[datasetId]/[collectionName]/[...subfieldNames].html +1 -1
- fides/ui-build/static/admin/dataset/[datasetId]/[collectionName].html +1 -1
- fides/ui-build/static/admin/dataset/[datasetId].html +1 -1
- fides/ui-build/static/admin/dataset/new.html +1 -1
- fides/ui-build/static/admin/dataset.html +1 -1
- fides/ui-build/static/admin/datastore-connection/[id].html +1 -1
- fides/ui-build/static/admin/datastore-connection/new.html +1 -1
- fides/ui-build/static/admin/datastore-connection.html +1 -1
- fides/ui-build/static/admin/index.html +1 -1
- fides/ui-build/static/admin/integrations/[id].html +1 -1
- fides/ui-build/static/admin/integrations.html +1 -1
- fides/ui-build/static/admin/lib/fides-ext-gpp.js +1 -1
- fides/ui-build/static/admin/lib/fides-tcf.js +1 -1
- 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/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.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/NgZHwKJoepGB5-XW8xdZo/_buildManifest.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/3215-c8c683b93919e0a5.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/3320-87c75df57a47487e.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/3662-420d9807c30008ab.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/3949-9888699e2ac564c4.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/4723-81d28e5be5c7b6d7.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/5574-a4047e826a8cd4c3.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/5834-bd9ed01c4ab2ef5c.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/5973-3226fe183b48668b.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/6277-cad7c7c8cf48dbec.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/6954-6eb480eb132239c3.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/7044-88111db2aca2cf65.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/7980-2597c279c30fbcda.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/9767-9af77524ed1648c1.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/add-systems-136bcbd20ac59bf5.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog-942d68a88b321067.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-214f8f89b94c3842.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-08e6d8bd6e91ee73.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/new-740824dfa6823e26.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset-5541ecd2f62711a5.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-a8e08ecb0c6c3a7c.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/integrations-1a6965d78bfb26b0.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/messaging-f263e6bacf0f2d19.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-b96ee3fea3920fcf.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-1b0f9469cb65abfc.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-eebd2f4ead19cfd6.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-4769f55b138073f7.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/domains-775f55b3f80cd452.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/organization-14def4ca3cc9cda5.js +0 -1
- fides/ui-build/static/admin/_next/static/css/957d0e4fea846ff0.css +0 -1
- {ethyca_fides-2.57.1b6.dist-info → ethyca_fides-2.57.1b8.dist-info}/LICENSE +0 -0
- {ethyca_fides-2.57.1b6.dist-info → ethyca_fides-2.57.1b8.dist-info}/WHEEL +0 -0
- {ethyca_fides-2.57.1b6.dist-info → ethyca_fides-2.57.1b8.dist-info}/entry_points.txt +0 -0
- {ethyca_fides-2.57.1b6.dist-info → ethyca_fides-2.57.1b8.dist-info}/top_level.txt +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{1150-73440d7b319558e8.js → 1150-d4a5eef84e70de22.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{2397-d8161100e3634f2c.js → 2397-c6d0dcb3b921555f.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{3086-be6b52546c3efc90.js → 3086-d099019708303444.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{3855-386aec4f0e0e89f1.js → 3855-4d5d936a58a0dd5f.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{3872-0da2c6a790542bd6.js → 3872-2b2bf5ebd4b0a70f.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{4481-0500c40ed13000c0.js → 4481-f2f57e7a75a90e79.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{5246-9fc6af1a6499e0a4.js → 5246-ac8b0fcb44b00af7.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{5258-3a650be9142cf914.js → 5258-a05dcab2f9315dab.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{5480-f5bec5e881f72f8d.js → 5480-c6c1fb87006e471a.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{5487-d96e1abc93f92631.js → 5487-509639439bf9fb46.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{5826-16e497af363a0cbc.js → 5826-e3970cd9440be33b.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{6315-dee79f6861c94d2d.js → 6315-daf94fa7520fb253.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{6372-f1b54f3cb4888660.js → 6372-41afe1e6a9181cc7.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{6853-2777b5ab5717fada.js → 6853-7f95c36e396d3fb8.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{7751-25e0c1307988ffd7.js → 7751-130668529ab1d0b6.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{79-ba88d0cf4c65aaa2.js → 79-1c326c00cf111c00.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{8433-969280d321d1c3a2.js → 8433-b2a96b825124b596.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{8499-07507004e8275df2.js → 8499-34620330ecf2ac53.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{9046-b18572b89f0aaa92.js → 9046-e7b9a3fd010b01ad.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{9282-1a5a2f6f4d9ed586.js → 9282-6ee061da1eb51d65.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{9999-f2e40d5b13343220.js → 9999-8600f6f495a80b38.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{404-1087258931760074.js → 404-8e0baa6e128803ab.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{ant-poc-b3b4d0a98450ffd1.js → ant-poc-39267961e03be6c5.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-experience-8b9f75fc0f131240.js → privacy-experience-ed38f18c095141fe.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-notices-da37afbe5ec81339.js → privacy-notices-7339b3cdf5d4da32.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{properties-c57b209feef7c2da.js → properties-b5b3196eba90246a.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{reporting-81ca1ac6f52ec342.js → reporting-38b8ec1a221610ff.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{consent-24bef021ee71e36c.js → consent-df2388d953c85c2a.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]/{[resourceUrn]-6cbd79481199812d.js → [resourceUrn]-5e851b9f27bda8a4.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/{[projectUrn]-46b9790da2fec05a.js → [projectUrn]-9f9112b22fdfb32a.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{projects-742849f39b646a2f.js → projects-ddca867936c89a72.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/resources/{[resourceUrn]-e7833c1c606081a9.js → [resourceUrn]-85e3d6f1b2afd3e7.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{resources-bed368d048ea6883.js → resources-9831226436d884b5.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/{[monitorId]-25eac2d4008cef3d.js → [monitorId]-5c37c3ad1c3cfba5.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{activity-0cfa8a9caf7c75c3.js → activity-a0749240265da17d.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{datamap-9cd0c40bef77b120.js → datamap-819ac99e7a56465a.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/{[...subfieldNames]-ab9bc1a3640547db.js → [...subfieldNames]-259d4a94861afe2b.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/{[collectionName]-17ec8385bb1fa6d4.js → [collectionName]-25283f5bcac8fa73.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/dataset/{[datasetId]-e14c1c07658f8a10.js → [datasetId]-aaedf8f2a849c97f.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{datastore-connection-b8eaa9b9d3832b30.js → datastore-connection-61adfcd5f7f69101.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{index-94e6d589c4edf360.js → index-1072281d6cfe8295.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{[id]-6b032de0a6c2c400.js → [id]-268918d8c1dfe82a.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{add-template-c0d6ae68ff7979c6.js → add-template-cd75949bee7497b6.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/{[id]-bbe5854b7d19b7e9.js → [id]-d1f4178b8a7e2145.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/{configure-4bad69cd42c9722c.js → configure-37e800a20e654064.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/properties/{[id]-b4c808a8a0287d11.js → [id]-92145503c4d2d75e.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/properties/{add-property-5a701477b006a63b.js → add-property-ab94805694ebd35c.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{properties-9a1899dfe052023e.js → properties-5e623dcd92418638.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/reporting/{datamap-449ad3b08750bfc2.js → datamap-710839776b9995ce.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{about-d073be113e9ca7b0.js → about-175d39bdd74f148c.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{custom-fields-ce9305fa04fecbb8.js → custom-fields-1262d596c0cdcd81.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domain-records-c5cd5fb578de9515.js → domain-records-f0c6e6034d37dbcf.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{email-templates-39c7ae3602ac69b2.js → email-templates-6ee49492a7769f89.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{locations-f35bd2d0c10aa58c.js → locations-deb754d42982562b.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{regulations-ba8c25b63bbf7dc2.js → regulations-f9e97decfe56b018.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/{test-datasets-73ef0438c85014bb.js → test-datasets-ae133b6e8e1107f2.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{systems-c320df35d51dc537.js → systems-4d6a17a7a24aca97.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{taxonomy-181ea5b0ac975239.js → taxonomy-46f47c04a01319cf.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/{[id]-622e16a17a11c096.js → [id]-5b752ba934baee94.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/pages/{user-management-aa872b21bb835d34.js → user-management-4fbb29cf0a611aae.js} +0 -0
- /fides/ui-build/static/admin/_next/static/chunks/{webpack-4df2ba5ee2d40f0a.js → webpack-815e3c35038201da.js} +0 -0
- /fides/ui-build/static/admin/_next/static/{NgZHwKJoepGB5-XW8xdZo → lO31cDp9wEzsNdiUnl8It}/_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-03-
|
11
|
+
"date": "2025-03-24T16:32:51-0600",
|
12
12
|
"dirty": false,
|
13
13
|
"error": null,
|
14
|
-
"full-revisionid": "
|
15
|
-
"version": "2.57.
|
14
|
+
"full-revisionid": "c371f453f33d1af4a35dfe6ae1d78c16b72576d8",
|
15
|
+
"version": "2.57.1b8"
|
16
16
|
}
|
17
17
|
''' # END VERSION_JSON
|
18
18
|
|
@@ -58,8 +58,10 @@ def patch_settings(
|
|
58
58
|
Only keys provided will be updated, others will be unaffected,
|
59
59
|
i.e. true PATCH behavior.
|
60
60
|
"""
|
61
|
-
|
62
|
-
|
61
|
+
# We use exclude_unset=True to ensure that only the provided keys are updated.
|
62
|
+
# This is particularly useful for allowing setting a specific key to None, while
|
63
|
+
# keeping the existing values for other keys that aren't provided in the payload data.
|
64
|
+
pruned_data = data.model_dump(exclude_unset=True)
|
63
65
|
logger.info("PATCHing application settings")
|
64
66
|
update_config: ApplicationConfig = ApplicationConfig.update_api_set(db, pruned_data)
|
65
67
|
|
@@ -9,7 +9,7 @@ from fideslang.models import Dataset as FideslangDataset
|
|
9
9
|
from pydantic import ValidationError as PydanticValidationError
|
10
10
|
from sqlalchemy import not_, select
|
11
11
|
from sqlalchemy.ext.asyncio import AsyncSession
|
12
|
-
from sqlalchemy.orm import Session
|
12
|
+
from sqlalchemy.orm import Session, load_only
|
13
13
|
from starlette import status
|
14
14
|
from starlette.status import (
|
15
15
|
HTTP_200_OK,
|
@@ -22,9 +22,10 @@ from fides.api.common_exceptions import KeyOrNameAlreadyExists, ValidationError
|
|
22
22
|
from fides.api.db.base_class import get_key_from_data
|
23
23
|
from fides.api.db.crud import list_resource_query
|
24
24
|
from fides.api.db.ctl_session import get_async_db
|
25
|
-
from fides.api.models.connectionconfig import ConnectionConfig
|
25
|
+
from fides.api.models.connectionconfig import ConnectionConfig, ConnectionType
|
26
26
|
from fides.api.models.datasetconfig import DatasetConfig
|
27
27
|
from fides.api.oauth.utils import verify_oauth_client
|
28
|
+
from fides.api.schemas.dataset import DatasetResponse
|
28
29
|
from fides.api.schemas.filter_params import FilterParams
|
29
30
|
from fides.api.schemas.taxonomy_extensions import (
|
30
31
|
DataCategory,
|
@@ -138,7 +139,7 @@ async def update_dataset(
|
|
138
139
|
@dataset_router.get(
|
139
140
|
"/dataset",
|
140
141
|
dependencies=[Security(verify_oauth_client, scopes=[CTL_DATASET_READ])],
|
141
|
-
response_model=Union[Page[
|
142
|
+
response_model=Union[Page[DatasetResponse], List[DatasetResponse]],
|
142
143
|
name="List datasets (optionally paginated)",
|
143
144
|
)
|
144
145
|
async def list_dataset_paginated(
|
@@ -149,7 +150,9 @@ async def list_dataset_paginated(
|
|
149
150
|
data_categories: Optional[List[str]] = Query(None),
|
150
151
|
exclude_saas_datasets: Optional[bool] = Query(False),
|
151
152
|
only_unlinked_datasets: Optional[bool] = Query(False),
|
152
|
-
|
153
|
+
connection_type: Optional[ConnectionType] = Query(None),
|
154
|
+
minimal: Optional[bool] = Query(False),
|
155
|
+
) -> Union[Page[DatasetResponse], List[DatasetResponse]]:
|
153
156
|
"""
|
154
157
|
Get a list of all of the Datasets.
|
155
158
|
If any pagination parameters (size or page) are provided, then the response will be paginated.
|
@@ -161,6 +164,25 @@ async def list_dataset_paginated(
|
|
161
164
|
|
162
165
|
query = select(CtlDataset)
|
163
166
|
|
167
|
+
if minimal:
|
168
|
+
# .options() allows us to modify how the query loads data by configuring the query's loading behavior
|
169
|
+
# load_only() optimizes the query by only loading the specified columns from the database
|
170
|
+
# This reduces memory usage and query time by not loading unnecessary columns
|
171
|
+
# The columns specified below are the minimal set needed for the DatasetResponse model
|
172
|
+
query = query.options( # type: ignore[attr-defined]
|
173
|
+
load_only(
|
174
|
+
CtlDataset.id,
|
175
|
+
CtlDataset.fides_key,
|
176
|
+
CtlDataset.organization_fides_key,
|
177
|
+
CtlDataset.name,
|
178
|
+
CtlDataset.created_at,
|
179
|
+
CtlDataset.updated_at,
|
180
|
+
CtlDataset.meta,
|
181
|
+
CtlDataset.fides_meta,
|
182
|
+
CtlDataset.description,
|
183
|
+
)
|
184
|
+
)
|
185
|
+
|
164
186
|
# Add filters for search and data categories
|
165
187
|
filter_params = FilterParams(search=search, data_categories=data_categories)
|
166
188
|
filtered_query = apply_filters_to_query(
|
@@ -170,6 +192,13 @@ async def list_dataset_paginated(
|
|
170
192
|
filter_params=filter_params,
|
171
193
|
)
|
172
194
|
|
195
|
+
# If applicable, filter by connection type
|
196
|
+
if connection_type:
|
197
|
+
filtered_query = filtered_query.where(
|
198
|
+
CtlDataset.fides_meta["namespace"]["connection_type"].as_string()
|
199
|
+
== connection_type.value
|
200
|
+
)
|
201
|
+
|
173
202
|
# If applicable, keep only unlinked datasets
|
174
203
|
if only_unlinked_datasets:
|
175
204
|
linked_datasets = select([DatasetConfig.ctl_dataset_id])
|
@@ -187,10 +216,18 @@ async def list_dataset_paginated(
|
|
187
216
|
)
|
188
217
|
|
189
218
|
if not page and not size:
|
190
|
-
|
219
|
+
results = await list_resource_query(db, filtered_query, CtlDataset)
|
220
|
+
response = [
|
221
|
+
DatasetResponse.model_validate(result.__dict__) for result in results
|
222
|
+
]
|
223
|
+
return response
|
191
224
|
|
192
225
|
pagination_params = Params(page=page or 1, size=size or 50)
|
193
|
-
|
226
|
+
results = await async_paginate(db, filtered_query, pagination_params)
|
227
|
+
results.items = [ # type: ignore[attr-defined]
|
228
|
+
DatasetResponse.model_validate(result.__dict__) for result in results.items # type: ignore[attr-defined]
|
229
|
+
]
|
230
|
+
return results
|
194
231
|
|
195
232
|
|
196
233
|
@dataset_router.get(
|
fides/api/main.py
CHANGED
@@ -232,10 +232,13 @@ async def log_request(request: Request, call_next: Callable) -> Response:
|
|
232
232
|
response = Response(status_code=500)
|
233
233
|
|
234
234
|
handler_time = datetime.now() - start
|
235
|
+
|
236
|
+
# Take the total time in seconds and convert it to milliseconds, rounding to 3 decimal places
|
237
|
+
total_time = round(handler_time.total_seconds() * 1000, 3)
|
235
238
|
logger.bind(
|
236
239
|
method=request.method,
|
237
240
|
status_code=response.status_code,
|
238
|
-
handler_time=f"{
|
241
|
+
handler_time=f"{total_time}ms",
|
239
242
|
path=request.url.path,
|
240
243
|
).info("Request received")
|
241
244
|
return response
|
fides/api/models/attachment.py
CHANGED
@@ -13,12 +13,14 @@ from fides.api.db.base_class import Base
|
|
13
13
|
from fides.api.models.fides_user import FidesUser # pylint: disable=unused-import
|
14
14
|
from fides.api.models.storage import StorageConfig # pylint: disable=unused-import
|
15
15
|
from fides.api.schemas.storage.storage import StorageDetails, StorageType
|
16
|
-
from fides.api.
|
17
|
-
LOCAL_FIDES_UPLOAD_DIRECTORY,
|
16
|
+
from fides.api.service.storage.s3 import (
|
18
17
|
generic_delete_from_s3,
|
19
18
|
generic_retrieve_from_s3,
|
19
|
+
generic_upload_to_s3,
|
20
|
+
)
|
21
|
+
from fides.api.service.storage.util import (
|
22
|
+
LOCAL_FIDES_UPLOAD_DIRECTORY,
|
20
23
|
get_local_filename,
|
21
|
-
upload_to_s3,
|
22
24
|
)
|
23
25
|
|
24
26
|
|
@@ -91,7 +93,6 @@ class Attachment(Base):
|
|
91
93
|
|
92
94
|
user = relationship(
|
93
95
|
"FidesUser",
|
94
|
-
backref="attachments",
|
95
96
|
lazy="selectin",
|
96
97
|
uselist=False,
|
97
98
|
)
|
@@ -114,13 +115,10 @@ class Attachment(Base):
|
|
114
115
|
if self.config.type == StorageType.s3:
|
115
116
|
bucket_name = f"{self.config.details[StorageDetails.BUCKET.value]}"
|
116
117
|
auth_method = self.config.details[StorageDetails.AUTH_METHOD.value]
|
117
|
-
|
118
|
+
generic_upload_to_s3(
|
118
119
|
storage_secrets=self.config.secrets,
|
119
|
-
data={},
|
120
120
|
bucket_name=bucket_name,
|
121
121
|
file_key=self.id,
|
122
|
-
resp_format=self.config.format,
|
123
|
-
privacy_request=None,
|
124
122
|
document=attachment,
|
125
123
|
auth_method=auth_method,
|
126
124
|
)
|
fides/api/models/comment.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
from enum import Enum as EnumType
|
2
|
-
from typing import Any
|
2
|
+
from typing import TYPE_CHECKING, Any
|
3
3
|
|
4
4
|
from sqlalchemy import Column
|
5
5
|
from sqlalchemy import Enum as EnumColumn
|
@@ -8,8 +8,10 @@ from sqlalchemy.ext.declarative import declared_attr
|
|
8
8
|
from sqlalchemy.orm import Session, relationship
|
9
9
|
|
10
10
|
from fides.api.db.base_class import Base
|
11
|
-
|
12
|
-
|
11
|
+
|
12
|
+
if TYPE_CHECKING:
|
13
|
+
from fides.api.models.attachment import Attachment
|
14
|
+
from fides.api.models.fides_user import FidesUser
|
13
15
|
|
14
16
|
|
15
17
|
class CommentType(str, EnumType):
|
@@ -78,7 +80,6 @@ class Comment(Base):
|
|
78
80
|
|
79
81
|
user = relationship(
|
80
82
|
"FidesUser",
|
81
|
-
backref="comments",
|
82
83
|
lazy="selectin",
|
83
84
|
uselist=False,
|
84
85
|
)
|
@@ -90,20 +91,19 @@ class Comment(Base):
|
|
90
91
|
uselist=True,
|
91
92
|
)
|
92
93
|
|
93
|
-
|
94
|
-
""
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
)
|
102
|
-
return db.execute(stmt).scalars().all()
|
94
|
+
attachments = relationship(
|
95
|
+
"Attachment",
|
96
|
+
secondary="attachment_reference",
|
97
|
+
primaryjoin="Comment.id == AttachmentReference.reference_id",
|
98
|
+
secondaryjoin="Attachment.id == AttachmentReference.attachment_id",
|
99
|
+
order_by="Attachment.created_at",
|
100
|
+
uselist=True,
|
101
|
+
)
|
103
102
|
|
104
103
|
def delete(self, db: Session) -> None:
|
105
104
|
"""Delete the comment and all associated references."""
|
106
|
-
|
107
|
-
for attachment in attachments:
|
108
|
-
attachment.
|
105
|
+
# Delete the comment
|
106
|
+
for attachment in self.attachments:
|
107
|
+
if len(attachment.references) == 1:
|
108
|
+
attachment.delete(db)
|
109
109
|
db.delete(self)
|
@@ -186,7 +186,7 @@ class ConnectionConfig(Base):
|
|
186
186
|
)
|
187
187
|
),
|
188
188
|
nullable=True,
|
189
|
-
) # Type
|
189
|
+
) # Type bytes in the db
|
190
190
|
last_test_timestamp = Column(DateTime(timezone=True))
|
191
191
|
last_test_succeeded = Column(Boolean)
|
192
192
|
disabled = Column(Boolean, server_default="f", default=False)
|
@@ -39,8 +39,10 @@ from fides.api.graph.config import (
|
|
39
39
|
CollectionAddress,
|
40
40
|
)
|
41
41
|
from fides.api.migrations.hash_migration_mixin import HashMigrationMixin
|
42
|
+
from fides.api.models.attachment import Attachment, AttachmentReference
|
42
43
|
from fides.api.models.audit_log import AuditLog
|
43
44
|
from fides.api.models.client import ClientDetail
|
45
|
+
from fides.api.models.comment import Comment, CommentReference
|
44
46
|
from fides.api.models.fides_user import FidesUser
|
45
47
|
from fides.api.models.manual_webhook import AccessManualWebhook
|
46
48
|
from fides.api.models.policy import (
|
@@ -166,6 +168,20 @@ class PrivacyRequest(
|
|
166
168
|
Policy,
|
167
169
|
backref="privacy_requests",
|
168
170
|
)
|
171
|
+
attachments = relationship(
|
172
|
+
Attachment,
|
173
|
+
secondary="attachment_reference",
|
174
|
+
primaryjoin="PrivacyRequest.id == AttachmentReference.reference_id",
|
175
|
+
secondaryjoin="Attachment.id == AttachmentReference.attachment_id",
|
176
|
+
order_by="Attachment.created_at",
|
177
|
+
)
|
178
|
+
comments = relationship(
|
179
|
+
Comment,
|
180
|
+
secondary="comment_reference",
|
181
|
+
primaryjoin="PrivacyRequest.id == CommentReference.reference_id",
|
182
|
+
secondaryjoin="Comment.id == CommentReference.comment_id",
|
183
|
+
order_by="Comment.created_at",
|
184
|
+
)
|
169
185
|
property_id = Column(String, nullable=True)
|
170
186
|
|
171
187
|
cancel_reason = Column(String(200))
|
@@ -1011,6 +1027,51 @@ class PrivacyRequest(
|
|
1011
1027
|
"""Return existing Consent Request Tasks for the current privacy request"""
|
1012
1028
|
return self.request_tasks.filter(RequestTask.action_type == ActionType.consent)
|
1013
1029
|
|
1030
|
+
def get_comment_by_id(self, db: Session, comment_id: str) -> Optional[Comment]:
|
1031
|
+
"""Get the comment associated with the privacy request"""
|
1032
|
+
comment = (
|
1033
|
+
db.query(Comment)
|
1034
|
+
.join(CommentReference, Comment.id == CommentReference.comment_id)
|
1035
|
+
.filter(
|
1036
|
+
CommentReference.reference_id
|
1037
|
+
== self.id, # Ensure the comment is linked to this privacy request
|
1038
|
+
Comment.id == comment_id, # Match the specific comment ID
|
1039
|
+
)
|
1040
|
+
.first()
|
1041
|
+
)
|
1042
|
+
if not comment:
|
1043
|
+
logger.info(
|
1044
|
+
f"Comment with id {comment_id} not found on privacy request {self.id}"
|
1045
|
+
)
|
1046
|
+
return comment
|
1047
|
+
|
1048
|
+
def get_attachment_by_id(
|
1049
|
+
self, db: Session, attachment_id: str
|
1050
|
+
) -> Optional[Attachment]:
|
1051
|
+
"""Get the attachment associated with the privacy request"""
|
1052
|
+
attachment = (
|
1053
|
+
db.query(Attachment)
|
1054
|
+
.join(
|
1055
|
+
AttachmentReference, Attachment.id == AttachmentReference.attachment_id
|
1056
|
+
)
|
1057
|
+
.filter(
|
1058
|
+
AttachmentReference.reference_id == self.id,
|
1059
|
+
Attachment.id == attachment_id,
|
1060
|
+
)
|
1061
|
+
.first()
|
1062
|
+
)
|
1063
|
+
if not attachment:
|
1064
|
+
logger.info(
|
1065
|
+
f"Attachment with id {attachment_id} not found on privacy request {self.id}"
|
1066
|
+
)
|
1067
|
+
return attachment
|
1068
|
+
|
1069
|
+
def delete_attachment_by_id(self, db: Session, attachment_id: str) -> None:
|
1070
|
+
"""Delete the attachment associated with the privacy request"""
|
1071
|
+
attachment = self.get_attachment_by_id(db, attachment_id)
|
1072
|
+
if attachment:
|
1073
|
+
attachment.delete(db)
|
1074
|
+
|
1014
1075
|
def get_existing_request_task(
|
1015
1076
|
self,
|
1016
1077
|
db: Session,
|
fides/api/oauth/utils.py
CHANGED
@@ -339,7 +339,16 @@ def has_permissions(
|
|
339
339
|
has_role: bool = _has_scope_via_role(
|
340
340
|
token_data=token_data, client=client, endpoint_scopes=endpoint_scopes
|
341
341
|
)
|
342
|
-
|
342
|
+
|
343
|
+
has_required_permissions = has_direct_scope or has_role
|
344
|
+
if not has_required_permissions:
|
345
|
+
scopes_required = ",".join(endpoint_scopes.scopes)
|
346
|
+
logger.debug(
|
347
|
+
"Authorization failed. Missing required scopes: {}. Neither direct scopes nor role-derived scopes were sufficient.",
|
348
|
+
scopes_required,
|
349
|
+
)
|
350
|
+
|
351
|
+
return has_required_permissions
|
343
352
|
|
344
353
|
|
345
354
|
def _has_scope_via_role(
|
@@ -385,16 +394,7 @@ def _has_direct_scopes(
|
|
385
394
|
|
386
395
|
def has_scope_subset(user_scopes: List[str], endpoint_scopes: SecurityScopes) -> bool:
|
387
396
|
"""Are the required scopes a subset of the scopes belonging to the user?"""
|
388
|
-
|
389
|
-
scopes_required = ",".join(endpoint_scopes.scopes)
|
390
|
-
scopes_provided = ",".join(user_scopes)
|
391
|
-
logger.debug(
|
392
|
-
"Auth token missing required scopes: {}. Scopes provided: {}.",
|
393
|
-
scopes_required,
|
394
|
-
scopes_provided,
|
395
|
-
)
|
396
|
-
return False
|
397
|
-
return True
|
397
|
+
return set(endpoint_scopes.scopes).issubset(user_scopes)
|
398
398
|
|
399
399
|
|
400
400
|
def create_temporary_user_for_login_flow(config: FidesConfig) -> FidesUser:
|
fides/api/schemas/dataset.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
from typing import Any, Dict, List, Optional, Union
|
2
2
|
|
3
|
-
from fideslang.models import Dataset
|
3
|
+
from fideslang.models import Dataset, DatasetCollection
|
4
4
|
from fideslang.validation import FidesKey
|
5
|
-
from pydantic import ConfigDict
|
5
|
+
from pydantic import ConfigDict, Field
|
6
6
|
|
7
7
|
from fides.api.schemas.api import BulkResponse, BulkUpdateFailed
|
8
8
|
from fides.api.schemas.base_class import FidesSchema
|
@@ -72,3 +72,23 @@ class DatasetReachability(FidesSchema):
|
|
72
72
|
|
73
73
|
reachable: bool
|
74
74
|
details: Optional[Union[str, List[Dict[str, Any]]]]
|
75
|
+
|
76
|
+
|
77
|
+
class DatasetResponse(Dataset):
|
78
|
+
"""
|
79
|
+
Dataset response model for API endpoints.
|
80
|
+
|
81
|
+
Note: This class extends the Dataset model from fideslang rather than having a proper
|
82
|
+
dedicated API response model. We had to make the collections field
|
83
|
+
Optional and allow null values to support the minimal=true parameter in API responses,
|
84
|
+
even though collections is required in the base fideslang Dataset model.
|
85
|
+
"""
|
86
|
+
|
87
|
+
collections: Optional[List[DatasetCollection]] = Field( # type: ignore
|
88
|
+
description="An array of objects that describe the Dataset's collections.",
|
89
|
+
default=None,
|
90
|
+
)
|
91
|
+
|
92
|
+
model_config = ConfigDict(
|
93
|
+
extra="ignore", from_attributes=False, coerce_numbers_to_str=True
|
94
|
+
)
|
@@ -67,7 +67,6 @@ from fides.api.tasks import DatabaseTask, celery_app
|
|
67
67
|
from fides.api.tasks.scheduled.scheduler import scheduler
|
68
68
|
from fides.api.util.collection_util import Row
|
69
69
|
from fides.api.util.logger import Pii, _log_exception, _log_warning
|
70
|
-
from fides.api.util.logger_context_utils import LoggerContextKeys, log_context
|
71
70
|
from fides.common.api.v1.urn_registry import (
|
72
71
|
PRIVACY_REQUEST_TRANSFER_TO_PARENT,
|
73
72
|
V1_URL_PREFIX,
|
@@ -270,7 +269,8 @@ def upload_access_results( # pylint: disable=R0912
|
|
270
269
|
|
271
270
|
|
272
271
|
@celery_app.task(base=DatabaseTask, bind=True)
|
273
|
-
|
272
|
+
# TODO: Add log_context back in, this is just for some temporary testing
|
273
|
+
# @log_context(capture_args={"privacy_request_id": LoggerContextKeys.privacy_request_id})
|
274
274
|
def run_privacy_request(
|
275
275
|
self: DatabaseTask,
|
276
276
|
privacy_request_id: str,
|
@@ -290,7 +290,10 @@ def run_privacy_request(
|
|
290
290
|
"""
|
291
291
|
resume_step: Optional[CurrentStep] = CurrentStep(from_step) if from_step else None # type: ignore
|
292
292
|
if from_step:
|
293
|
-
logger.
|
293
|
+
with logger.contextualize(
|
294
|
+
privacy_request_id=privacy_request_id,
|
295
|
+
):
|
296
|
+
logger.info("Resuming privacy request from checkpoint: '{}'", from_step)
|
294
297
|
|
295
298
|
with self.get_new_session() as session:
|
296
299
|
privacy_request = PrivacyRequest.get(db=session, object_id=privacy_request_id)
|
@@ -302,7 +305,8 @@ def run_privacy_request(
|
|
302
305
|
with logger.contextualize(
|
303
306
|
privacy_request_source=(
|
304
307
|
privacy_request.source.value if privacy_request.source else None
|
305
|
-
)
|
308
|
+
),
|
309
|
+
privacy_request_id=privacy_request.id,
|
306
310
|
):
|
307
311
|
if privacy_request.status == PrivacyRequestStatus.canceled:
|
308
312
|
logger.info("Terminating privacy request: request canceled.")
|
@@ -0,0 +1,133 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from io import BytesIO
|
4
|
+
from typing import Any, Dict, Optional
|
5
|
+
|
6
|
+
from boto3.s3.transfer import TransferConfig
|
7
|
+
from botocore.exceptions import ClientError, ParamValidationError
|
8
|
+
from fideslang.validation import AnyHttpUrlString
|
9
|
+
from loguru import logger
|
10
|
+
|
11
|
+
from fides.api.schemas.storage.storage import StorageSecrets
|
12
|
+
from fides.api.util.aws_util import get_s3_client
|
13
|
+
from fides.config import CONFIG
|
14
|
+
|
15
|
+
|
16
|
+
def create_presigned_url_for_s3(
|
17
|
+
s3_client: Any, bucket_name: str, file_key: str
|
18
|
+
) -> AnyHttpUrlString:
|
19
|
+
""" "Generate a presigned URL to share an S3 object
|
20
|
+
|
21
|
+
:param s3_client: s3 base client
|
22
|
+
:param bucket_name: string
|
23
|
+
:param file_key: string
|
24
|
+
:return: Presigned URL as string.
|
25
|
+
"""
|
26
|
+
response = s3_client.generate_presigned_url(
|
27
|
+
"get_object",
|
28
|
+
Params={"Bucket": bucket_name, "Key": file_key},
|
29
|
+
ExpiresIn=CONFIG.security.subject_request_download_link_ttl_seconds,
|
30
|
+
)
|
31
|
+
|
32
|
+
# The response contains the presigned URL
|
33
|
+
return response
|
34
|
+
|
35
|
+
|
36
|
+
def generic_upload_to_s3( # pylint: disable=R0913
|
37
|
+
storage_secrets: Dict[StorageSecrets, Any],
|
38
|
+
bucket_name: str,
|
39
|
+
file_key: str,
|
40
|
+
auth_method: str,
|
41
|
+
document: BytesIO,
|
42
|
+
) -> Optional[AnyHttpUrlString]:
|
43
|
+
"""
|
44
|
+
Uploads arbitrary data to S3 returned from an access request.
|
45
|
+
Handles both small and large uploads.
|
46
|
+
"""
|
47
|
+
logger.info("Starting S3 Upload of {}", file_key)
|
48
|
+
|
49
|
+
try:
|
50
|
+
s3_client = get_s3_client(auth_method, storage_secrets)
|
51
|
+
|
52
|
+
# Define a transfer configuration for multipart uploads
|
53
|
+
transfer_config = TransferConfig(
|
54
|
+
multipart_threshold=5 * 1024 * 1024, # 5 MB threshold for multipart uploads
|
55
|
+
multipart_chunksize=5 * 1024 * 1024, # 5 MB chunk size
|
56
|
+
)
|
57
|
+
|
58
|
+
try:
|
59
|
+
# Check if the document is a file-like object or raw bytes
|
60
|
+
if isinstance(document, bytes):
|
61
|
+
document = BytesIO(document) # Wrap raw bytes in a file-like object
|
62
|
+
|
63
|
+
# Use upload_fileobj for efficient uploads (handles both small and large files)
|
64
|
+
s3_client.upload_fileobj(
|
65
|
+
Fileobj=document,
|
66
|
+
Bucket=bucket_name,
|
67
|
+
Key=file_key,
|
68
|
+
Config=transfer_config,
|
69
|
+
)
|
70
|
+
except Exception as e:
|
71
|
+
logger.error("Encountered error while uploading S3 object: {}", e)
|
72
|
+
raise e
|
73
|
+
|
74
|
+
# Generate a presigned URL for the uploaded file
|
75
|
+
presigned_url: AnyHttpUrlString = create_presigned_url_for_s3(
|
76
|
+
s3_client, bucket_name, file_key
|
77
|
+
)
|
78
|
+
|
79
|
+
return presigned_url
|
80
|
+
except ClientError as e:
|
81
|
+
logger.error(
|
82
|
+
"Encountered error while uploading and generating link for S3 object: {}", e
|
83
|
+
)
|
84
|
+
raise e
|
85
|
+
except ParamValidationError as e:
|
86
|
+
raise ValueError(f"The parameters you provided are incorrect: {e}")
|
87
|
+
|
88
|
+
|
89
|
+
def generic_retrieve_from_s3(
|
90
|
+
storage_secrets: Dict[StorageSecrets, Any],
|
91
|
+
bucket_name: str,
|
92
|
+
file_key: str,
|
93
|
+
auth_method: str,
|
94
|
+
) -> Optional[BytesIO]:
|
95
|
+
"""Retrieves arbitrary data from s3"""
|
96
|
+
logger.info("Starting S3 Retrieve of {}", file_key)
|
97
|
+
|
98
|
+
try:
|
99
|
+
s3_client = get_s3_client(auth_method, storage_secrets)
|
100
|
+
try:
|
101
|
+
response = s3_client.get_object(Bucket=bucket_name, Key=file_key)
|
102
|
+
return response["Body"].read()
|
103
|
+
except Exception as e:
|
104
|
+
logger.error("Encountered error while retrieving s3 object: {}", e)
|
105
|
+
raise e
|
106
|
+
except ClientError as e:
|
107
|
+
logger.error("Encountered error while retrieving s3 object: {}", e)
|
108
|
+
raise e
|
109
|
+
except ParamValidationError as e:
|
110
|
+
raise ValueError(f"The parameters you provided are incorrect: {e}")
|
111
|
+
|
112
|
+
|
113
|
+
def generic_delete_from_s3(
|
114
|
+
storage_secrets: Dict[StorageSecrets, Any],
|
115
|
+
bucket_name: str,
|
116
|
+
file_key: str,
|
117
|
+
auth_method: str,
|
118
|
+
) -> None:
|
119
|
+
"""Deletes arbitrary data from s3"""
|
120
|
+
logger.info("Starting S3 Delete of {}", file_key)
|
121
|
+
|
122
|
+
try:
|
123
|
+
s3_client = get_s3_client(auth_method, storage_secrets)
|
124
|
+
try:
|
125
|
+
s3_client.delete_object(Bucket=bucket_name, Key=file_key)
|
126
|
+
except Exception as e:
|
127
|
+
logger.error("Encountered error while deleting s3 object: {}", e)
|
128
|
+
raise e
|
129
|
+
except ClientError as e:
|
130
|
+
logger.error("Encountered error while deleting s3 object: {}", e)
|
131
|
+
raise e
|
132
|
+
except ParamValidationError as e:
|
133
|
+
raise ValueError(f"The parameters you provided are incorrect: {e}")
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import os
|
2
|
+
|
3
|
+
LOCAL_FIDES_UPLOAD_DIRECTORY = "fides_uploads"
|
4
|
+
|
5
|
+
|
6
|
+
def get_local_filename(file_key: str) -> str:
|
7
|
+
"""Verifies that the local storage directory exists"""
|
8
|
+
if not os.path.exists(LOCAL_FIDES_UPLOAD_DIRECTORY):
|
9
|
+
os.makedirs(LOCAL_FIDES_UPLOAD_DIRECTORY)
|
10
|
+
return f"{LOCAL_FIDES_UPLOAD_DIRECTORY}/{file_key}"
|
fides/api/tasks/__init__.py
CHANGED
@@ -79,7 +79,9 @@ class DatabaseTask(Task): # pylint: disable=W0223
|
|
79
79
|
# but a new session is instantiated each time the method is invoked
|
80
80
|
# to prevent session overlap when requests are executing concurrently
|
81
81
|
# when in task_always_eager mode (i.e. without proper workers)
|
82
|
-
|
82
|
+
new_session = self._sessionmaker()
|
83
|
+
logger.debug(f"DatabaseTaskSession ID: {id(new_session)}. Self ID: {id(self)}")
|
84
|
+
return new_session
|
83
85
|
|
84
86
|
|
85
87
|
def _create_celery(config: FidesConfig = CONFIG) -> Celery:
|