ethyca-fides 2.68.1b2__py2.py3-none-any.whl → 2.68.1b4__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.

Files changed (318) hide show
  1. {ethyca_fides-2.68.1b2.dist-info → ethyca_fides-2.68.1b4.dist-info}/METADATA +3 -1
  2. {ethyca_fides-2.68.1b2.dist-info → ethyca_fides-2.68.1b4.dist-info}/RECORD +253 -232
  3. fides/_version.py +3 -3
  4. fides/api/alembic/migrations/versions/90502bcda282_update_request_tasks_add_polling_async.py +35 -0
  5. fides/api/alembic/migrations/versions/b1a2c3d4e5f6_add_location_to_privacy_request.py +26 -0
  6. fides/api/api/v1/api.py +2 -0
  7. fides/api/api/v1/endpoints/dsr_package_link.py +167 -0
  8. fides/api/api/v1/endpoints/privacy_request_endpoints.py +31 -1
  9. fides/api/api/v1/endpoints/user_endpoints.py +4 -0
  10. fides/api/common_exceptions.py +12 -3
  11. fides/api/models/detection_discovery/core.py +6 -0
  12. fides/api/models/privacy_request/privacy_request.py +1 -0
  13. fides/api/models/privacy_request/request_task.py +25 -0
  14. fides/api/models/privacy_request/webhook.py +33 -1
  15. fides/api/oauth/utils.py +122 -57
  16. fides/api/schemas/application_config.py +7 -0
  17. fides/api/schemas/connection_configuration/connection_type_system_map.py +6 -0
  18. fides/api/schemas/enums/__init__.py +0 -0
  19. fides/api/schemas/enums/connection_category.py +20 -0
  20. fides/api/schemas/enums/integration_feature.py +23 -0
  21. fides/api/schemas/external_https.py +9 -0
  22. fides/api/schemas/privacy_center_config.py +48 -19
  23. fides/api/schemas/privacy_request.py +16 -0
  24. fides/api/schemas/saas/display_info.py +19 -0
  25. fides/api/schemas/saas/saas_config.py +2 -0
  26. fides/api/schemas/storage/storage.py +4 -0
  27. fides/api/service/async_dsr/__init__.py +0 -0
  28. fides/api/service/async_dsr/async_dsr_service.py +75 -0
  29. fides/api/service/connectors/saas_connector.py +5 -6
  30. fides/api/service/privacy_request/dsr_package/dsr_report_builder.py +6 -4
  31. fides/api/service/privacy_request/request_runner_service.py +41 -4
  32. fides/api/service/privacy_request/request_service.py +50 -2
  33. fides/api/service/storage/storage_uploader_service.py +80 -5
  34. fides/api/service/storage/streaming/__init__.py +42 -0
  35. fides/api/service/storage/streaming/base_storage_client.py +61 -0
  36. fides/api/service/storage/streaming/dsr_storage.py +98 -0
  37. fides/api/service/storage/streaming/retry.py +282 -0
  38. fides/api/service/storage/streaming/s3/__init__.py +5 -0
  39. fides/api/service/storage/streaming/s3/s3_storage_client.py +113 -0
  40. fides/api/service/storage/streaming/s3/streaming_s3.py +196 -0
  41. fides/api/service/storage/streaming/schemas.py +173 -0
  42. fides/api/service/storage/streaming/smart_open_client.py +265 -0
  43. fides/api/service/storage/streaming/smart_open_streaming_storage.py +998 -0
  44. fides/api/service/storage/streaming/storage_client_factory.py +60 -0
  45. fides/api/task/graph_task.py +4 -4
  46. fides/api/task/manual/manual_task_graph_task.py +3 -4
  47. fides/api/util/connection_type.py +20 -0
  48. fides/api/util/text.py +51 -0
  49. fides/common/api/v1/urn_registry.py +3 -0
  50. fides/config/execution_settings.py +4 -0
  51. fides/service/privacy_request/privacy_request_service.py +84 -9
  52. fides/ui-build/static/admin/404.html +1 -1
  53. fides/ui-build/static/admin/_next/static/LRCvfOqg1kP5kGnkD84G4/_buildManifest.js +1 -0
  54. fides/ui-build/static/admin/_next/static/chunks/1099-b973dfdfc5c3de90.js +1 -0
  55. fides/ui-build/static/admin/_next/static/chunks/1345-b60d1f3442379c73.js +1 -0
  56. fides/ui-build/static/admin/_next/static/chunks/{1817-c90365325f8a3d75.js → 1817-74692de5d760a664.js} +1 -1
  57. fides/ui-build/static/admin/_next/static/chunks/{1975.e5cc7a1ccd477671.js → 1975.78e719130cfe3fd6.js} +1 -1
  58. fides/ui-build/static/admin/_next/static/chunks/{2921-46f9465c2852a46b.js → 2921-2d9261e8e2e127c0.js} +1 -1
  59. fides/ui-build/static/admin/_next/static/chunks/3620-ebd89f91b82661e8.js +1 -0
  60. fides/ui-build/static/admin/_next/static/chunks/3729-ccf90cdaae158f39.js +1 -0
  61. fides/ui-build/static/admin/_next/static/chunks/3847-2759bf1f47a1d29e.js +1 -0
  62. fides/ui-build/static/admin/_next/static/chunks/3855-4174a4d4c205d6e8.js +1 -0
  63. fides/ui-build/static/admin/_next/static/chunks/3872-660aba76572c811b.js +1 -0
  64. fides/ui-build/static/admin/_next/static/chunks/{3923-a33633feba5e655e.js → 3923-c6cdc2e5278ae9a7.js} +1 -1
  65. fides/ui-build/static/admin/_next/static/chunks/{401-741bb31b586b7c96.js → 401-8bc2c6c84172c096.js} +1 -1
  66. fides/ui-build/static/admin/_next/static/chunks/{4121-94354b50a41f8497.js → 4121-9a4ebceff9accb7f.js} +1 -1
  67. fides/ui-build/static/admin/_next/static/chunks/431-86ad2beeb93c95c9.js +1 -0
  68. fides/ui-build/static/admin/_next/static/chunks/4608-4d31340b0d0157c1.js +1 -0
  69. fides/ui-build/static/admin/_next/static/chunks/4786-aaef673b30c19e2e.js +1 -0
  70. fides/ui-build/static/admin/_next/static/chunks/4808-a654c7f7a1ca62c8.js +1 -0
  71. fides/ui-build/static/admin/_next/static/chunks/4844-cd7e1d0c7bb94094.js +1 -0
  72. fides/ui-build/static/admin/_next/static/chunks/5258-bc4a25d43e4aa07d.js +1 -0
  73. fides/ui-build/static/admin/_next/static/chunks/5487-37c78c4799ba5223.js +1 -0
  74. fides/ui-build/static/admin/_next/static/chunks/549-2213dc1c34143cda.js +1 -0
  75. fides/ui-build/static/admin/_next/static/chunks/{6084-02abe12327fc3dbc.js → 6084-55cc66e7c94f0686.js} +1 -1
  76. fides/ui-build/static/admin/_next/static/chunks/{6853-270261ef5537a106.js → 6853-313ce974d33432fb.js} +1 -1
  77. fides/ui-build/static/admin/_next/static/chunks/6954-021bd06d0ab59c3c.js +1 -0
  78. fides/ui-build/static/admin/_next/static/chunks/7476-2fc286c2a9125eb8.js +1 -0
  79. fides/ui-build/static/admin/_next/static/chunks/7630-b9a41262a69edf5e.js +1 -0
  80. fides/ui-build/static/admin/_next/static/chunks/768-034e121688a3bbdd.js +1 -0
  81. fides/ui-build/static/admin/_next/static/chunks/{787-5ba991cad1f7664a.js → 787-8df7118742e84908.js} +1 -1
  82. fides/ui-build/static/admin/_next/static/chunks/79-d2ace89108ead8ae.js +1 -0
  83. fides/ui-build/static/admin/_next/static/chunks/796-2de6dac5f311d54a.js +1 -0
  84. fides/ui-build/static/admin/_next/static/chunks/8002-cfdc6574bd841892.js +1 -0
  85. fides/ui-build/static/admin/_next/static/chunks/9046-c44e41da49338c6c.js +1 -0
  86. fides/ui-build/static/admin/_next/static/chunks/9676.b7d5d1d90b9da224.js +1 -0
  87. fides/ui-build/static/admin/_next/static/chunks/{9826-8c81c97a72510fcf.js → 9826-d9addbd5ac990fa4.js} +1 -1
  88. fides/ui-build/static/admin/_next/static/chunks/9951-6ee5c0a23951a07f.js +1 -0
  89. fides/ui-build/static/admin/_next/static/chunks/pages/{404-9174cdb70126c2c5.js → 404-9644eb282f2dcd71.js} +1 -1
  90. fides/ui-build/static/admin/_next/static/chunks/pages/{_app-2c10f6b217b7978b.js → _app-284cba7174fa1f16.js} +136 -135
  91. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{manual-621416493c89ef01.js → manual-42b7fd34712f49bd.js} +1 -1
  92. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{multiple-0b9908c3e1dfe49e.js → multiple-4f164eab0960bbe0.js} +1 -1
  93. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems-985d3c9179e69d7f.js +1 -0
  94. fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure/{add-vendors-5bb1b31ae8752250.js → add-vendors-61090926e5f98a5d.js} +1 -1
  95. fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure-17ffe691b91cee2e.js +1 -0
  96. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{[id]-4e4d9426743b5cb4.js → [id]-95c13bca5c1e575e.js} +1 -1
  97. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-experience-d72460348fadcab8.js → privacy-experience-609399510a60beb9.js} +1 -1
  98. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{[id]-3e7ddc252da00c98.js → [id]-d7d8f228ac74b26e.js} +1 -1
  99. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{new-35a7c305beee9428.js → new-821c0f82d5a2b7d4.js} +1 -1
  100. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices-8365782543cf6ab9.js +1 -0
  101. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{properties-ab96939421639153.js → properties-40a7aa65f4d13cf9.js} +1 -1
  102. fides/ui-build/static/admin/_next/static/chunks/pages/consent/reporting-e4bacfc5c2ed2324.js +1 -0
  103. fides/ui-build/static/admin/_next/static/chunks/pages/{consent-13240e3ca77acfeb.js → consent-70c5c6aa5389d99f.js} +1 -1
  104. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]/{[resourceUrn]-aad6047a4604b945.js → [resourceUrn]-adc500a03e239857.js} +1 -1
  105. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/{[projectUrn]-bd37b407c80c6986.js → [projectUrn]-3207f62e5012611b.js} +1 -1
  106. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects-7b42dee0fb696658.js +1 -0
  107. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/resources/{[resourceUrn]-b6b98cea25dd94fa.js → [resourceUrn]-c8b3d090e4ba60d3.js} +1 -1
  108. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog-31a45ea2ca2a7f04.js +1 -0
  109. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-6172c2eb539319fd.js +1 -0
  110. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]-945d354ff057fb03.js +1 -0
  111. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-d9795e00f39cf4e9.js +1 -0
  112. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/activity-657833fd8528280f.js +1 -0
  113. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/detection/{[resourceUrn]-31e6c54794a9883e.js → [resourceUrn]-22eec362dfbb1d2a.js} +1 -1
  114. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{detection-2822a423a7ad0550.js → detection-4decce5ef996e563.js} +1 -1
  115. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/discovery/{[resourceUrn]-f98dd251babb7e28.js → [resourceUrn]-01acdd1ad492fd89.js} +1 -1
  116. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{discovery-56eb4c014f0d96a3.js → discovery-85fdbf4cde60d910.js} +1 -1
  117. fides/ui-build/static/admin/_next/static/chunks/pages/{datamap-8f88dc31c5144ea8.js → datamap-3a4b89fb21d14753.js} +1 -1
  118. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/[...subfieldNames]-cb8d303f56091bd5.js +1 -0
  119. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]-401c8be76d9daec7.js +1 -0
  120. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]-97e2d375b21cfe43.js +1 -0
  121. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/new-40ef544ca1f2c9b9.js +1 -0
  122. fides/ui-build/static/admin/_next/static/chunks/pages/dataset-e3c763f8e71f8e24.js +1 -0
  123. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{[id]-67a7fe58b96ea739.js → [id]-152e5d15705ec072.js} +1 -1
  124. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/new-651b10cae0e99a05.js +1 -0
  125. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection-03c54bc9fb18d2b0.js +1 -0
  126. fides/ui-build/static/admin/_next/static/chunks/pages/{index-876bfd7210040cec.js → index-3d19b9ffa15a928a.js} +1 -1
  127. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-4b0bb4ccfb237d41.js +1 -0
  128. fides/ui-build/static/admin/_next/static/chunks/pages/integrations-78d4e0c14654148b.js +1 -0
  129. fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{[id]-6e796c3fe632280b.js → [id]-72cb360a6d14e701.js} +1 -1
  130. fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{add-template-fa0f3841c5bdfdeb.js → add-template-0ed67cf774d5cbf5.js} +1 -1
  131. fides/ui-build/static/admin/_next/static/chunks/pages/messaging-b06a2204e2a5b667.js +1 -0
  132. fides/ui-build/static/admin/_next/static/chunks/pages/poc/ant-components-7050899b3f792129.js +1 -0
  133. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{AntForm-11503454a62d8d7b.js → AntForm-7c3466f4d5797e55.js} +1 -1
  134. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikAntFormItem-a504941807bdb7f1.js → FormikAntFormItem-8de252f25871bab9.js} +1 -1
  135. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikControlled-0119403c8ff97f83.js → FormikControlled-cd6de0da47f980cf.js} +1 -1
  136. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikField-94f6d57d6c94ddf7.js → FormikField-7c238a881fe30e28.js} +1 -1
  137. fides/ui-build/static/admin/_next/static/chunks/pages/poc/{forms-ed1a3ae09d72df89.js → forms-d4f3e8f67f76f146.js} +1 -1
  138. fides/ui-build/static/admin/_next/static/chunks/pages/poc/table-migration-c9220e20c1d93758.js +1 -0
  139. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-b9d6886a3f157120.js +1 -0
  140. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-9c1fd7867b2d80d7.js +1 -0
  141. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-fc959ed21dbce38c.js +1 -0
  142. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure-44a4a638dcb2722a.js +1 -0
  143. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-1433c9f9501a884f.js +1 -0
  144. fides/ui-build/static/admin/_next/static/chunks/pages/properties/{[id]-41976b28503623cd.js → [id]-16e0b42cb342aa5f.js} +1 -1
  145. fides/ui-build/static/admin/_next/static/chunks/pages/properties/{add-property-cb438d8f5ec6007a.js → add-property-ebd114a86b809391.js} +1 -1
  146. fides/ui-build/static/admin/_next/static/chunks/pages/{properties-b6db7036993709b3.js → properties-901be5fa4a48f48c.js} +1 -1
  147. fides/ui-build/static/admin/_next/static/chunks/pages/reporting/datamap-da9ced1e20681154.js +1 -0
  148. fides/ui-build/static/admin/_next/static/chunks/pages/settings/about/alpha-0174554c0ac5958f.js +1 -0
  149. fides/ui-build/static/admin/_next/static/chunks/pages/settings/about-6f45ddbf675e66d2.js +1 -0
  150. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent/[configuration_id]/[purpose_id]-275c49e6089c5c9f.js +1 -0
  151. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-1a8d05e19f06d857.js +1 -0
  152. fides/ui-build/static/admin/_next/static/chunks/pages/settings/custom-fields-49d86b9ca4523ca6.js +1 -0
  153. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domain-records-386368bf7cb31771.js → domain-records-f71b4b95d91db926.js} +1 -1
  154. fides/ui-build/static/admin/_next/static/chunks/pages/settings/domains-a595cad18cf04673.js +1 -0
  155. fides/ui-build/static/admin/_next/static/chunks/pages/settings/email-templates-6f7f9751689b042c.js +1 -0
  156. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{locations-b41fb5ad277088ab.js → locations-e2c88d7f779fe604.js} +1 -1
  157. fides/ui-build/static/admin/_next/static/chunks/pages/settings/organization-c65acd2b7ab04753.js +1 -0
  158. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{regulations-a94dfeea43fbca7d.js → regulations-c1c699eeb40a9dc0.js} +1 -1
  159. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/test-datasets-a274e2191b87e315.js +1 -0
  160. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/{[id]-18b316e2dad73731.js → [id]-4a48b4f996a64957.js} +1 -1
  161. fides/ui-build/static/admin/_next/static/chunks/pages/systems-30debc87925634d9.js +1 -0
  162. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-ca625b1296a029f0.js +1 -0
  163. fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/{[id]-3237881945acc0ee.js → [id]-7a3180b235eb8846.js} +1 -1
  164. fides/ui-build/static/admin/_next/static/chunks/pages/{user-management-a3a50d9d79066935.js → user-management-5e2d0acf575252ca.js} +1 -1
  165. fides/ui-build/static/admin/_next/static/chunks/{webpack-69658aeaf6155d89.js → webpack-4502d4d67006b48f.js} +1 -1
  166. fides/ui-build/static/admin/_next/static/css/43d0c0fc207767eb.css +1 -0
  167. fides/ui-build/static/admin/add-systems/manual.html +1 -1
  168. fides/ui-build/static/admin/add-systems/multiple.html +1 -1
  169. fides/ui-build/static/admin/add-systems.html +1 -1
  170. fides/ui-build/static/admin/consent/configure/add-vendors.html +1 -1
  171. fides/ui-build/static/admin/consent/configure.html +1 -1
  172. fides/ui-build/static/admin/consent/privacy-experience/[id].html +1 -1
  173. fides/ui-build/static/admin/consent/privacy-experience/new.html +1 -1
  174. fides/ui-build/static/admin/consent/privacy-experience.html +1 -1
  175. fides/ui-build/static/admin/consent/privacy-notices/[id].html +1 -1
  176. fides/ui-build/static/admin/consent/privacy-notices/new.html +1 -1
  177. fides/ui-build/static/admin/consent/privacy-notices.html +1 -1
  178. fides/ui-build/static/admin/consent/properties.html +1 -1
  179. fides/ui-build/static/admin/consent/reporting.html +1 -1
  180. fides/ui-build/static/admin/consent.html +1 -1
  181. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn].html +1 -1
  182. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn].html +1 -1
  183. fides/ui-build/static/admin/data-catalog/[systemId]/projects.html +1 -1
  184. fides/ui-build/static/admin/data-catalog/[systemId]/resources/[resourceUrn].html +1 -1
  185. fides/ui-build/static/admin/data-catalog/[systemId]/resources.html +1 -1
  186. fides/ui-build/static/admin/data-catalog.html +1 -1
  187. fides/ui-build/static/admin/data-discovery/action-center/[monitorId]/[systemId].html +1 -1
  188. fides/ui-build/static/admin/data-discovery/action-center/[monitorId].html +1 -1
  189. fides/ui-build/static/admin/data-discovery/action-center.html +1 -1
  190. fides/ui-build/static/admin/data-discovery/activity.html +1 -1
  191. fides/ui-build/static/admin/data-discovery/detection/[resourceUrn].html +1 -1
  192. fides/ui-build/static/admin/data-discovery/detection.html +1 -1
  193. fides/ui-build/static/admin/data-discovery/discovery/[resourceUrn].html +1 -1
  194. fides/ui-build/static/admin/data-discovery/discovery.html +1 -1
  195. fides/ui-build/static/admin/datamap.html +1 -1
  196. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName]/[...subfieldNames].html +1 -1
  197. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName].html +1 -1
  198. fides/ui-build/static/admin/dataset/[datasetId].html +1 -1
  199. fides/ui-build/static/admin/dataset/new.html +1 -1
  200. fides/ui-build/static/admin/dataset.html +1 -1
  201. fides/ui-build/static/admin/datastore-connection/[id].html +1 -1
  202. fides/ui-build/static/admin/datastore-connection/new.html +1 -1
  203. fides/ui-build/static/admin/datastore-connection.html +1 -1
  204. fides/ui-build/static/admin/index.html +1 -1
  205. fides/ui-build/static/admin/integrations/[id].html +1 -1
  206. fides/ui-build/static/admin/integrations.html +1 -1
  207. fides/ui-build/static/admin/lib/fides-preview.js +1 -1
  208. fides/ui-build/static/admin/lib/fides-tcf.js +2 -2
  209. fides/ui-build/static/admin/login/[provider].html +1 -1
  210. fides/ui-build/static/admin/login.html +1 -1
  211. fides/ui-build/static/admin/messaging/[id].html +1 -1
  212. fides/ui-build/static/admin/messaging/add-template.html +1 -1
  213. fides/ui-build/static/admin/messaging.html +1 -1
  214. fides/ui-build/static/admin/poc/ant-components.html +1 -1
  215. fides/ui-build/static/admin/poc/form-experiments/AntForm.html +1 -1
  216. fides/ui-build/static/admin/poc/form-experiments/FormikAntFormItem.html +1 -1
  217. fides/ui-build/static/admin/poc/form-experiments/FormikControlled.html +1 -1
  218. fides/ui-build/static/admin/poc/form-experiments/FormikField.html +1 -1
  219. fides/ui-build/static/admin/poc/form-experiments/FormikSpreadField.html +1 -1
  220. fides/ui-build/static/admin/poc/forms.html +1 -1
  221. fides/ui-build/static/admin/poc/table-migration.html +1 -1
  222. fides/ui-build/static/admin/privacy-requests/[id].html +1 -1
  223. fides/ui-build/static/admin/privacy-requests/configure/messaging.html +1 -1
  224. fides/ui-build/static/admin/privacy-requests/configure/storage.html +1 -1
  225. fides/ui-build/static/admin/privacy-requests/configure.html +1 -1
  226. fides/ui-build/static/admin/privacy-requests.html +1 -1
  227. fides/ui-build/static/admin/properties/[id].html +1 -1
  228. fides/ui-build/static/admin/properties/add-property.html +1 -1
  229. fides/ui-build/static/admin/properties.html +1 -1
  230. fides/ui-build/static/admin/reporting/datamap.html +1 -1
  231. fides/ui-build/static/admin/settings/about/alpha.html +1 -1
  232. fides/ui-build/static/admin/settings/about.html +1 -1
  233. fides/ui-build/static/admin/settings/consent/[configuration_id]/[purpose_id].html +1 -1
  234. fides/ui-build/static/admin/settings/consent.html +1 -1
  235. fides/ui-build/static/admin/settings/custom-fields.html +1 -1
  236. fides/ui-build/static/admin/settings/domain-records.html +1 -1
  237. fides/ui-build/static/admin/settings/domains.html +1 -1
  238. fides/ui-build/static/admin/settings/email-templates.html +1 -1
  239. fides/ui-build/static/admin/settings/locations.html +1 -1
  240. fides/ui-build/static/admin/settings/organization.html +1 -1
  241. fides/ui-build/static/admin/settings/regulations.html +1 -1
  242. fides/ui-build/static/admin/systems/configure/[id]/test-datasets.html +1 -1
  243. fides/ui-build/static/admin/systems/configure/[id].html +1 -1
  244. fides/ui-build/static/admin/systems.html +1 -1
  245. fides/ui-build/static/admin/taxonomy.html +1 -1
  246. fides/ui-build/static/admin/user-management/new.html +1 -1
  247. fides/ui-build/static/admin/user-management/profile/[id].html +1 -1
  248. fides/ui-build/static/admin/user-management.html +1 -1
  249. fides/ui-build/static/admin/_next/static/chunks/203-0c6cadcda98bdd33.js +0 -1
  250. fides/ui-build/static/admin/_next/static/chunks/3450-9314e1b15df8a8da.js +0 -1
  251. fides/ui-build/static/admin/_next/static/chunks/3855-4267fd8193e7f525.js +0 -1
  252. fides/ui-build/static/admin/_next/static/chunks/3872-ac5feefd40b61ae3.js +0 -1
  253. fides/ui-build/static/admin/_next/static/chunks/409-5bc4369b80a8c11d.js +0 -1
  254. fides/ui-build/static/admin/_next/static/chunks/4230-1ebc8c0ab293a077.js +0 -1
  255. fides/ui-build/static/admin/_next/static/chunks/431-a34d7ceff17c2169.js +0 -1
  256. fides/ui-build/static/admin/_next/static/chunks/4608-557fb24665b2e4bf.js +0 -1
  257. fides/ui-build/static/admin/_next/static/chunks/5309-ffdec884eec79d29.js +0 -1
  258. fides/ui-build/static/admin/_next/static/chunks/5574-831167a8da90e2e6.js +0 -1
  259. fides/ui-build/static/admin/_next/static/chunks/6662-499c189f932a35aa.js +0 -1
  260. fides/ui-build/static/admin/_next/static/chunks/6780-7d28e030f6516e5d.js +0 -1
  261. fides/ui-build/static/admin/_next/static/chunks/6882-7cc1d14e27a80c10.js +0 -1
  262. fides/ui-build/static/admin/_next/static/chunks/6954-7784e8d5ad6b8110.js +0 -1
  263. fides/ui-build/static/admin/_next/static/chunks/7476-4de465016d3433b4.js +0 -1
  264. fides/ui-build/static/admin/_next/static/chunks/7630-2a5c57787632693d.js +0 -1
  265. fides/ui-build/static/admin/_next/static/chunks/7725-c79513b04113112b.js +0 -1
  266. fides/ui-build/static/admin/_next/static/chunks/79-98cfab20bb831137.js +0 -1
  267. fides/ui-build/static/admin/_next/static/chunks/796-0b768155bf20505f.js +0 -1
  268. fides/ui-build/static/admin/_next/static/chunks/8735-f84afcc50885883c.js +0 -1
  269. fides/ui-build/static/admin/_next/static/chunks/9046-97a972cc8a8ed24d.js +0 -1
  270. fides/ui-build/static/admin/_next/static/chunks/9226-318dadf1c050ecda.js +0 -1
  271. fides/ui-build/static/admin/_next/static/chunks/9676.9e6828b42ef05e06.js +0 -1
  272. fides/ui-build/static/admin/_next/static/chunks/9951-4df2b67e0def5500.js +0 -1
  273. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems-18e96ce81dab51a4.js +0 -1
  274. fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure-54d7c7310763c66d.js +0 -1
  275. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices-6bc3b73a21576869.js +0 -1
  276. fides/ui-build/static/admin/_next/static/chunks/pages/consent/reporting-fe3d6887fecf0f86.js +0 -1
  277. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects-e4770acf7044e2f5.js +0 -1
  278. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog-0db635c3483c9da8.js +0 -1
  279. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-0c0e0a7798345541.js +0 -1
  280. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]-3c56e5fe072a44c6.js +0 -1
  281. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-58827eb86516931f.js +0 -1
  282. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/activity-6a90131dcecd694c.js +0 -1
  283. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/[...subfieldNames]-145fe9e4cfcb231d.js +0 -1
  284. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]-8a1e5d140785c1e9.js +0 -1
  285. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]-227b5db4b472a6a7.js +0 -1
  286. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/new-8401f17fe5d9a1dc.js +0 -1
  287. fides/ui-build/static/admin/_next/static/chunks/pages/dataset-7d77b3ad069be268.js +0 -1
  288. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/new-90a8df230cb89877.js +0 -1
  289. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection-cfb25b02abb8da71.js +0 -1
  290. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-4e286a1e501a0c73.js +0 -1
  291. fides/ui-build/static/admin/_next/static/chunks/pages/integrations-3fdc55d4c129e618.js +0 -1
  292. fides/ui-build/static/admin/_next/static/chunks/pages/messaging-8f9c006b6166f002.js +0 -1
  293. fides/ui-build/static/admin/_next/static/chunks/pages/poc/ant-components-6ba7ae4f26c06cb0.js +0 -1
  294. fides/ui-build/static/admin/_next/static/chunks/pages/poc/table-migration-e8db3ad525e7ddbd.js +0 -1
  295. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-c14dd24592369467.js +0 -1
  296. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-100d7d03930629a8.js +0 -1
  297. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-6f8d1b3ec83cfcf0.js +0 -1
  298. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure-3ce15577435d47cb.js +0 -1
  299. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-709bcb0bc6a5382d.js +0 -1
  300. fides/ui-build/static/admin/_next/static/chunks/pages/reporting/datamap-4bc3e281409265cc.js +0 -1
  301. fides/ui-build/static/admin/_next/static/chunks/pages/settings/about/alpha-1ea40fcd6b4268bf.js +0 -1
  302. fides/ui-build/static/admin/_next/static/chunks/pages/settings/about-65c7600fadc6e55a.js +0 -1
  303. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent/[configuration_id]/[purpose_id]-33dab986141b3663.js +0 -1
  304. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-1195042727c399ed.js +0 -1
  305. fides/ui-build/static/admin/_next/static/chunks/pages/settings/custom-fields-71b98858ecb4e097.js +0 -1
  306. fides/ui-build/static/admin/_next/static/chunks/pages/settings/domains-cf427e04f862b5d2.js +0 -1
  307. fides/ui-build/static/admin/_next/static/chunks/pages/settings/email-templates-eabeeec5bf2773c6.js +0 -1
  308. fides/ui-build/static/admin/_next/static/chunks/pages/settings/organization-ee56698ae3a6a78b.js +0 -1
  309. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/test-datasets-0e2e98cc38ee5499.js +0 -1
  310. fides/ui-build/static/admin/_next/static/chunks/pages/systems-c32589c86081b750.js +0 -1
  311. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-a8f09bf8f3204ca7.js +0 -1
  312. fides/ui-build/static/admin/_next/static/css/a72179b1754aadd3.css +0 -1
  313. fides/ui-build/static/admin/_next/static/qvk5eMANVfwYkdURE7fgG/_buildManifest.js +0 -1
  314. {ethyca_fides-2.68.1b2.dist-info → ethyca_fides-2.68.1b4.dist-info}/WHEEL +0 -0
  315. {ethyca_fides-2.68.1b2.dist-info → ethyca_fides-2.68.1b4.dist-info}/entry_points.txt +0 -0
  316. {ethyca_fides-2.68.1b2.dist-info → ethyca_fides-2.68.1b4.dist-info}/licenses/LICENSE +0 -0
  317. {ethyca_fides-2.68.1b2.dist-info → ethyca_fides-2.68.1b4.dist-info}/top_level.txt +0 -0
  318. /fides/ui-build/static/admin/_next/static/{qvk5eMANVfwYkdURE7fgG → LRCvfOqg1kP5kGnkD84G4}/_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-08-19T14:51:50-0700",
11
+ "date": "2025-08-27T12:07:27-0600",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "047dc431c1e669789ec8aa19ededd438909b8c0c",
15
- "version": "2.68.1b2"
14
+ "full-revisionid": "062904c4ee33fadc4f937ccfd3fd2f2e2a2cbae8",
15
+ "version": "2.68.1b4"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -0,0 +1,35 @@
1
+ """Update Request Tasks
2
+
3
+ Revision ID: 90502bcda282
4
+ Revises: 3baf42d251a6
5
+ Create Date: 2025-08-05 16:31:45.335384
6
+
7
+ """
8
+
9
+ import sqlalchemy as sa
10
+ from alembic import op
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = "90502bcda282"
14
+ down_revision = "3baf42d251a6"
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+ async_task_type = sa.Enum("manual", "polling", "callback", name="asynctasktype")
19
+
20
+
21
+ def upgrade():
22
+ async_task_type.create(op.get_bind(), checkfirst=True)
23
+ op.add_column(
24
+ "requesttask",
25
+ sa.Column(
26
+ "async_type",
27
+ async_task_type,
28
+ nullable=True,
29
+ ),
30
+ )
31
+
32
+
33
+ def downgrade():
34
+ op.drop_column("requesttask", "async_type")
35
+ async_task_type.drop(op.get_bind(), checkfirst=True)
@@ -0,0 +1,26 @@
1
+ """add location to privacy request
2
+
3
+ Revision ID: b1a2c3d4e5f6
4
+ Revises: 2f3c1a2d6b10
5
+ Create Date: 2025-08-06 18:15:00.000000
6
+
7
+ """
8
+
9
+ import sqlalchemy as sa
10
+ from alembic import op
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = "b1a2c3d4e5f6"
14
+ down_revision = "90502bcda282"
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade():
20
+ # Add location column to privacyrequest table
21
+ op.add_column("privacyrequest", sa.Column("location", sa.String(), nullable=True))
22
+
23
+
24
+ def downgrade():
25
+ # Remove location column from privacyrequest table
26
+ op.drop_column("privacyrequest", "location")
fides/api/api/v1/api.py CHANGED
@@ -5,6 +5,7 @@ from fides.api.api.v1.endpoints import (
5
5
  consent_request_endpoints,
6
6
  dataset_config_endpoints,
7
7
  drp_endpoints,
8
+ dsr_package_link,
8
9
  encryption_endpoints,
9
10
  identity_verification_endpoints,
10
11
  manual_webhook_endpoints,
@@ -32,6 +33,7 @@ api_router.include_router(connection_endpoints.router)
32
33
  api_router.include_router(consent_request_endpoints.router)
33
34
  api_router.include_router(dataset_config_endpoints.router)
34
35
  api_router.include_router(drp_endpoints.router)
36
+ api_router.include_router(dsr_package_link.router)
35
37
  api_router.include_router(encryption_endpoints.router)
36
38
  api_router.include_router(masking_endpoints.router)
37
39
  api_router.include_router(oauth_endpoints.router)
@@ -0,0 +1,167 @@
1
+ import uuid
2
+
3
+ from fastapi import Depends, HTTPException, Request, Response
4
+ from fastapi.responses import RedirectResponse
5
+ from sqlalchemy.orm import Session
6
+ from starlette.status import (
7
+ HTTP_302_FOUND,
8
+ HTTP_400_BAD_REQUEST,
9
+ HTTP_401_UNAUTHORIZED,
10
+ HTTP_403_FORBIDDEN,
11
+ HTTP_404_NOT_FOUND,
12
+ HTTP_422_UNPROCESSABLE_ENTITY,
13
+ )
14
+
15
+ from fides.api.api.deps import get_db
16
+ from fides.api.common_exceptions import AuthenticationError, AuthorizationError
17
+ from fides.api.models.privacy_request import PrivacyRequest
18
+ from fides.api.models.storage import get_active_default_storage_config
19
+ from fides.api.oauth.utils import validate_download_token
20
+ from fides.api.schemas.privacy_request import PrivacyRequestStatus
21
+ from fides.api.schemas.storage.storage import StorageType
22
+ from fides.api.service.storage.streaming.s3 import S3StorageClient
23
+ from fides.api.util.api_router import APIRouter
24
+ from fides.api.util.endpoint_utils import fides_limiter
25
+ from fides.common.api.v1.urn_registry import PRIVACY_CENTER_DSR_PACKAGE, V1_URL_PREFIX
26
+ from fides.config import CONFIG
27
+
28
+ router = APIRouter(tags=["Privacy Center"], prefix=V1_URL_PREFIX)
29
+
30
+
31
+ def get_privacy_request_or_error(
32
+ privacy_request_id: str, db: Session
33
+ ) -> PrivacyRequest:
34
+ """Load the privacy request or throw a 404"""
35
+ # Note: UUID format validation is now done earlier in the endpoint
36
+ privacy_request = PrivacyRequest.get(db, object_id=privacy_request_id)
37
+
38
+ if not privacy_request:
39
+ raise HTTPException(
40
+ status_code=HTTP_404_NOT_FOUND,
41
+ detail=f"No privacy request found with id '{privacy_request_id}'.",
42
+ )
43
+
44
+ if privacy_request.deleted_at is not None:
45
+ raise HTTPException(
46
+ status_code=HTTP_422_UNPROCESSABLE_ENTITY,
47
+ detail=f"Privacy request with id {privacy_request_id} has been deleted.",
48
+ )
49
+
50
+ return privacy_request
51
+
52
+
53
+ def raise_error(status_code: int, detail: str) -> None:
54
+ """Raise an HTTPException with the given status code and detail"""
55
+ raise HTTPException(
56
+ status_code=status_code,
57
+ detail=detail,
58
+ )
59
+
60
+
61
+ @router.get(
62
+ PRIVACY_CENTER_DSR_PACKAGE,
63
+ status_code=HTTP_302_FOUND,
64
+ )
65
+ @fides_limiter.limit(CONFIG.security.public_request_rate_limit)
66
+ def get_access_results_urls(
67
+ privacy_request_id: str,
68
+ token: str,
69
+ db: Session = Depends(get_db),
70
+ *,
71
+ request: Request, # required for rate limiting
72
+ response: Response, # required for rate limiting
73
+ ) -> RedirectResponse:
74
+ """
75
+ Public endpoint for retrieving access results URLs for a privacy request.
76
+ This endpoint generates fresh presigned URLs and redirects to the first available result.
77
+ This endpoint is designed to be accessible via email links sent to end users.
78
+ No authentication is required, but a valid download token is required for security.
79
+ Rate limiting is applied for additional security.
80
+
81
+ privacy_request_id parameter is required in the URL path.
82
+ token parameter is required as a query parameter for security.
83
+ """
84
+ # --------------Security checks--------------
85
+ # First validate the privacy request ID format to prevent SSRF attacks
86
+ # This is a simple string check that doesn't require database access
87
+ if not privacy_request_id.startswith("pri_"):
88
+ raise_error(
89
+ HTTP_400_BAD_REQUEST,
90
+ f"Invalid privacy request ID format: '{privacy_request_id}'. Must start with 'pri_' followed by a valid UUID v4.",
91
+ )
92
+
93
+ # Extract the UUID part after the prefix
94
+ uuid_part = privacy_request_id[4:] # Remove "pri_" prefix
95
+
96
+ try:
97
+ uuid.UUID(uuid_part, version=4)
98
+ except ValueError:
99
+ raise_error(
100
+ HTTP_400_BAD_REQUEST,
101
+ f"Invalid privacy request ID format: '{privacy_request_id}'. Must start with 'pri_' followed by a valid UUID v4.",
102
+ )
103
+
104
+ try:
105
+ # Validate the download token before proceeding
106
+ validate_download_token(token, privacy_request_id)
107
+ except AuthenticationError as e:
108
+ raise_error(HTTP_401_UNAUTHORIZED, str(e.detail))
109
+ except AuthorizationError as e:
110
+ raise_error(HTTP_403_FORBIDDEN, str(e.detail))
111
+
112
+ # --------------Data checks--------------
113
+ storage_config = get_active_default_storage_config(db)
114
+ privacy_request = get_privacy_request_or_error(privacy_request_id, db)
115
+
116
+ if not storage_config:
117
+ raise_error(
118
+ HTTP_400_BAD_REQUEST, "No active default storage configuration found."
119
+ )
120
+
121
+ if privacy_request.status != PrivacyRequestStatus.complete:
122
+ raise_error(
123
+ HTTP_400_BAD_REQUEST,
124
+ f"Access results for privacy request '{privacy_request.id}' are not available because the request is not complete.",
125
+ )
126
+
127
+ if (
128
+ not privacy_request.access_result_urls
129
+ or not privacy_request.access_result_urls.get("access_result_urls")
130
+ ):
131
+ raise_error(
132
+ HTTP_404_NOT_FOUND,
133
+ f"No access results found for privacy request '{privacy_request.id}'.",
134
+ )
135
+
136
+ # --------------Processing--------------
137
+ file_name = f"{privacy_request.id}.zip"
138
+
139
+ # At this point, storage_config is guaranteed to exist due to earlier validation
140
+ # and we've already checked that it's not None above
141
+ assert storage_config is not None
142
+
143
+ if storage_config.type != StorageType.s3:
144
+ # Handle all other storage types (transcend, ethyca, local, etc.)
145
+ raise_error(
146
+ HTTP_400_BAD_REQUEST,
147
+ f"Storage type '{storage_config.type}' is not supported for download redirects. "
148
+ "Only S3 storage is supported for this endpoint.",
149
+ )
150
+
151
+ # Get bucket name from storage config
152
+ bucket_name = storage_config.details.get("bucket")
153
+ if not bucket_name:
154
+ raise_error(HTTP_400_BAD_REQUEST, "S3 bucket name not found in storage config.")
155
+
156
+ try:
157
+ # Use S3StorageClient for cleaner presigned URL generation
158
+ s3_storage_client = S3StorageClient(storage_config.secrets)
159
+ result_url = s3_storage_client.generate_presigned_url(
160
+ bucket=bucket_name,
161
+ key=file_name,
162
+ )
163
+ except Exception as e:
164
+ raise_error(HTTP_400_BAD_REQUEST, f"Failed to generate presigned URL: {str(e)}")
165
+
166
+ # Convert the URL to string for RedirectResponse
167
+ return RedirectResponse(url=str(result_url), status_code=HTTP_302_FOUND)
@@ -50,6 +50,7 @@ from fides.api.common_exceptions import (
50
50
  IdentityVerificationException,
51
51
  ManualWebhookFieldsUnset,
52
52
  NoCachedManualWebhookEntry,
53
+ PrivacyRequestError,
53
54
  TraversalError,
54
55
  ValidationError,
55
56
  )
@@ -123,6 +124,7 @@ from fides.api.util.endpoint_utils import validate_start_and_end_filters
123
124
  from fides.api.util.enums import ColumnSort
124
125
  from fides.api.util.fuzzy_search_utils import get_decrypted_identities_automaton
125
126
  from fides.api.util.storage_util import StorageJSONEncoder
127
+ from fides.api.util.text import normalize_location_code
126
128
  from fides.common.api.scope_registry import (
127
129
  PRIVACY_REQUEST_CALLBACK_RESUME,
128
130
  PRIVACY_REQUEST_CREATE,
@@ -175,7 +177,6 @@ from fides.service.dataset.dataset_config_service import (
175
177
  )
176
178
  from fides.service.messaging.messaging_service import MessagingService
177
179
  from fides.service.privacy_request.privacy_request_service import (
178
- PrivacyRequestError,
179
180
  PrivacyRequestService,
180
181
  _process_privacy_request_restart,
181
182
  _requeue_privacy_request,
@@ -403,6 +404,7 @@ def _filter_privacy_request_queryset(
403
404
  errored_lt: Optional[datetime] = None,
404
405
  errored_gt: Optional[datetime] = None,
405
406
  external_id: Optional[str] = None,
407
+ location: Optional[str] = None,
406
408
  action_type: Optional[ActionType] = None,
407
409
  include_consent_webhook_requests: Optional[bool] = False,
408
410
  include_deleted_requests: Optional[bool] = False,
@@ -539,6 +541,29 @@ def _filter_privacy_request_queryset(
539
541
  query = query.filter(PrivacyRequest.id.ilike(f"%{request_id}%"))
540
542
  if external_id:
541
543
  query = query.filter(PrivacyRequest.external_id.ilike(f"{external_id}%"))
544
+ if location:
545
+ # Support filtering by exact location match or country prefix
546
+ # e.g., "US" matches both "US" and "US-CA", "US-NY", etc.
547
+ # "US-CA" matches only "US-CA"
548
+ # Also normalize input to handle underscores and case insensitivity
549
+
550
+ try:
551
+ normalized_location = normalize_location_code(location)
552
+ except ValueError:
553
+ # If normalization fails, treat as no results to prevent errors
554
+ query = query.filter(False)
555
+ else:
556
+ if "-" in normalized_location:
557
+ # Exact match for subdivision codes
558
+ query = query.filter(PrivacyRequest.location == normalized_location)
559
+ else:
560
+ # Country code - match country or any subdivision of that country
561
+ query = query.filter(
562
+ or_(
563
+ PrivacyRequest.location == normalized_location,
564
+ PrivacyRequest.location.ilike(f"{normalized_location}-%"),
565
+ )
566
+ )
542
567
  if status:
543
568
  query = query.filter(PrivacyRequest.status.in_(status))
544
569
  if created_lt:
@@ -685,6 +710,7 @@ def _shared_privacy_request_search(
685
710
  errored_lt: Optional[datetime] = None,
686
711
  errored_gt: Optional[datetime] = None,
687
712
  external_id: Optional[str] = None,
713
+ location: Optional[str] = None,
688
714
  action_type: Optional[ActionType] = None,
689
715
  verbose: Optional[bool] = False,
690
716
  include_identities: Optional[bool] = False,
@@ -723,6 +749,7 @@ def _shared_privacy_request_search(
723
749
  errored_lt,
724
750
  errored_gt,
725
751
  external_id,
752
+ location,
726
753
  action_type,
727
754
  None,
728
755
  include_deleted_requests,
@@ -796,6 +823,7 @@ def get_request_status(
796
823
  errored_lt: Optional[datetime] = None,
797
824
  errored_gt: Optional[datetime] = None,
798
825
  external_id: Optional[str] = None,
826
+ location: Optional[str] = None,
799
827
  action_type: Optional[ActionType] = None,
800
828
  verbose: Optional[bool] = False,
801
829
  include_identities: Optional[bool] = False,
@@ -836,6 +864,7 @@ def get_request_status(
836
864
  errored_lt=errored_lt,
837
865
  errored_gt=errored_gt,
838
866
  external_id=external_id,
867
+ location=location,
839
868
  action_type=action_type,
840
869
  verbose=verbose,
841
870
  include_identities=include_identities,
@@ -890,6 +919,7 @@ def privacy_request_search(
890
919
  errored_lt=privacy_request_filter.errored_lt,
891
920
  errored_gt=privacy_request_filter.errored_gt,
892
921
  external_id=privacy_request_filter.external_id,
922
+ location=privacy_request_filter.location,
893
923
  action_type=privacy_request_filter.action_type,
894
924
  verbose=privacy_request_filter.verbose,
895
925
  include_identities=privacy_request_filter.include_identities,
@@ -250,6 +250,10 @@ def logout_oauth_client(
250
250
  if authorization is None:
251
251
  raise AuthenticationError(detail="Authentication Failure")
252
252
 
253
+ # Validate that the token looks like a valid JWE token (5 segments separated by dots)
254
+ if not authorization or authorization.count(".") != 4:
255
+ return None
256
+
253
257
  try:
254
258
  token_data = json.loads(
255
259
  extract_payload(authorization, CONFIG.security.app_encryption_key)
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import List
3
+ from typing import Dict, List, Optional
4
4
 
5
5
  from fastapi import HTTPException, status
6
6
  from starlette.status import (
@@ -175,8 +175,8 @@ class RequestTaskNotFound(BaseException):
175
175
  """Privacy Request Task Not Found"""
176
176
 
177
177
 
178
- class AwaitingAsyncTaskCallback(BaseException):
179
- """Request Task is Awaiting Processing - Awaiting Async Task Callback"""
178
+ class AwaitingAsyncTask(BaseException):
179
+ """Request Task is Awaiting Processing - Awaiting Async Task"""
180
180
 
181
181
 
182
182
  class UpstreamTasksNotReady(BaseException):
@@ -373,6 +373,15 @@ class InvalidScopeError(HTTPException):
373
373
  )
374
374
 
375
375
 
376
+ class PrivacyRequestError(Exception):
377
+ """Base exception for privacy request operations."""
378
+
379
+ def __init__(self, message: str, data: Optional[Dict] = None):
380
+ self.message = message
381
+ self.data = data
382
+ super().__init__(message)
383
+
384
+
376
385
  class KeyOrNameAlreadyExists(Exception):
377
386
  """A resource already exists with this key or name."""
378
387
 
@@ -432,11 +432,17 @@ class StagedResourceAncestor(Base):
432
432
 
433
433
  # Execute batch when it reaches the desired size
434
434
  if len(current_batch) >= batch_size:
435
+ logger.debug(
436
+ f"Inserting batch of {len(current_batch)} staged resource ancestor links"
437
+ )
435
438
  db.execute(stmt_text, current_batch)
436
439
  current_batch = []
437
440
 
438
441
  # Execute any remaining items in the final batch
439
442
  if current_batch:
443
+ logger.debug(
444
+ f"Inserting batch of {len(current_batch)} staged resource ancestor links"
445
+ )
440
446
  db.execute(stmt_text, current_batch)
441
447
 
442
448
 
@@ -222,6 +222,7 @@ class PrivacyRequest(
222
222
  canceled_at = Column(DateTime(timezone=True), nullable=True)
223
223
  consent_preferences = Column(MutableList.as_mutable(JSONB), nullable=True)
224
224
  source = Column(EnumColumn(PrivacyRequestSource), nullable=True)
225
+ location = Column(String, nullable=True)
225
226
 
226
227
  # A PrivacyRequest can be soft deleted, so we store when it was deleted
227
228
  deleted_at = Column(DateTime(timezone=True), nullable=True)
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ from enum import Enum as EnumType
5
6
  from typing import TYPE_CHECKING, List, Optional, Tuple
6
7
 
7
8
  from loguru import logger
@@ -15,6 +16,7 @@ from sqlalchemy_utils.types.encrypted.encrypted_type import (
15
16
  )
16
17
 
17
18
  from fides.api.db.base_class import Base, JSONTypeOverride # type: ignore[attr-defined]
19
+ from fides.api.db.util import EnumColumn
18
20
  from fides.api.graph.config import (
19
21
  ROOT_COLLECTION_ADDRESS,
20
22
  TERMINATOR_ADDRESS,
@@ -67,6 +69,24 @@ class TraversalDetails(FidesSchema):
67
69
  )
68
70
 
69
71
 
72
+ class AsyncTaskType(EnumType):
73
+ """
74
+ Enum for asynchronous RequestTask types
75
+
76
+ These tasks differ from our regular tasks in that they are not finished on the same process that they are created,
77
+ but rather are put into a pause state and then triggered to completion by a different process
78
+
79
+ manual: A task that is manually triggered by the user
80
+ polling: A task that is triggered by a polling mechanism
81
+ callback: A task that is triggered by a callback from an external system
82
+
83
+ """
84
+
85
+ manual = "manual"
86
+ polling = "polling"
87
+ callback = "callback"
88
+
89
+
70
90
  # TODO: At some point we will refactor this model to store all task types in a common table that links to tables with specific task attributes.
71
91
  class RequestTask(WorkerTask, Base):
72
92
  """
@@ -145,6 +165,11 @@ class RequestTask(WorkerTask, Base):
145
165
 
146
166
  # For async tasks awaiting callback
147
167
  callback_succeeded = Column(Boolean)
168
+ # to recognize Polling async task
169
+ async_type = Column(
170
+ EnumColumn(AsyncTaskType, native_enum=True),
171
+ nullable=True,
172
+ )
148
173
 
149
174
  # Stores a serialized collection that can be transformed back into a Collection to help
150
175
  # execute the current task
@@ -13,12 +13,17 @@ from fides.api.models.policy import PolicyPreWebhook, WebhookDirection
13
13
  from fides.api.models.pre_approval_webhook import PreApprovalWebhook
14
14
  from fides.api.models.privacy_request.request_task import RequestTask
15
15
  from fides.api.oauth.jwt import generate_jwe
16
- from fides.api.schemas.external_https import RequestTaskJWE, WebhookJWE
16
+ from fides.api.schemas.external_https import (
17
+ DownloadTokenJWE,
18
+ RequestTaskJWE,
19
+ WebhookJWE,
20
+ )
17
21
  from fides.api.schemas.policy import ActionType
18
22
  from fides.api.schemas.privacy_request import PrivacyRequestStatus
19
23
  from fides.api.schemas.redis_cache import Identity
20
24
  from fides.common.api.scope_registry import (
21
25
  PRIVACY_REQUEST_CALLBACK_RESUME,
26
+ PRIVACY_REQUEST_READ_ACCESS_RESULTS,
22
27
  PRIVACY_REQUEST_REVIEW,
23
28
  )
24
29
  from fides.config import CONFIG
@@ -92,3 +97,30 @@ def generate_request_task_callback_jwe(request_task: RequestTask) -> str:
92
97
  json.dumps(jwe.model_dump(mode="json")),
93
98
  CONFIG.security.app_encryption_key,
94
99
  )
100
+
101
+
102
+ def generate_privacy_request_download_token(privacy_request_id: str) -> str:
103
+ """
104
+ Generate a JWE token for users to download their privacy request access package.
105
+ This is currently used for the DSR package link endpoint which provides a redirect
106
+ to a presigned URL for the access results.
107
+ This token expires based on the configured TTL for security.
108
+ """
109
+ from datetime import timedelta
110
+
111
+ now = datetime.now()
112
+ # Use the configured TTL from security settings
113
+ expiration = now + timedelta(
114
+ seconds=CONFIG.security.subject_request_download_link_ttl_seconds
115
+ )
116
+
117
+ jwe = DownloadTokenJWE(
118
+ privacy_request_id=privacy_request_id,
119
+ scopes=[PRIVACY_REQUEST_READ_ACCESS_RESULTS],
120
+ iat=now.isoformat(),
121
+ exp=expiration.isoformat(),
122
+ )
123
+ return generate_jwe(
124
+ json.dumps(jwe.model_dump(mode="json")),
125
+ CONFIG.security.app_encryption_key,
126
+ )