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/api/oauth/utils.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import json
4
- from datetime import datetime
4
+ from datetime import datetime, timedelta
5
5
  from functools import update_wrapper
6
6
  from types import FunctionType
7
7
  from typing import Any, Callable, Dict, List, Optional, Tuple
@@ -32,7 +32,11 @@ from fides.api.models.pre_approval_webhook import PreApprovalWebhook
32
32
  from fides.api.models.privacy_request import RequestTask
33
33
  from fides.api.oauth.roles import get_scopes_from_roles
34
34
  from fides.api.request_context import set_user_id
35
- from fides.api.schemas.external_https import RequestTaskJWE, WebhookJWE
35
+ from fides.api.schemas.external_https import (
36
+ DownloadTokenJWE,
37
+ RequestTaskJWE,
38
+ WebhookJWE,
39
+ )
36
40
  from fides.api.schemas.oauth import OAuth2ClientCredentialsBearer
37
41
  from fides.common.api.v1.urn_registry import TOKEN, V1_URL_PREFIX
38
42
  from fides.config import CONFIG, FidesConfig
@@ -49,63 +53,28 @@ oauth2_scheme = OAuth2ClientCredentialsBearer(
49
53
 
50
54
  def extract_payload(jwe_string: str, encryption_key: str) -> str:
51
55
  """Given a jwe, extracts the payload and returns it in string form."""
52
- return jwe.decrypt(jwe_string, encryption_key)
56
+ try:
57
+ decrypted_payload = jwe.decrypt(jwe_string, encryption_key)
58
+ return decrypted_payload.decode("utf-8")
59
+ except exceptions.JWEError as e:
60
+ logger.debug("Failed to decrypt JWE: {}", e)
61
+ raise e
53
62
 
54
63
 
55
- def is_token_expired(issued_at: datetime | None, token_duration_min: int) -> bool:
56
- """Returns True if the datetime is earlier than token_duration_min ago."""
57
- if not issued_at:
64
+ def is_token_expired(
65
+ issued_at: Optional[datetime], token_duration_minutes: int
66
+ ) -> bool:
67
+ """Check if a token has expired based on its issued_at timestamp and duration."""
68
+ if issued_at is None:
58
69
  return True
70
+ expiration_time = issued_at + timedelta(minutes=token_duration_minutes)
71
+ return datetime.now() > expiration_time
59
72
 
60
- return (datetime.now() - issued_at).total_seconds() / 60.0 > token_duration_min
61
-
62
-
63
- def copy_func(source_function: Callable) -> Callable:
64
- """Based on http://stackoverflow.com/a/6528148/190597 (Glenn Maynard)"""
65
- target_function = FunctionType(
66
- source_function.__code__,
67
- source_function.__globals__,
68
- name=source_function.__name__,
69
- argdefs=source_function.__defaults__,
70
- closure=source_function.__closure__,
71
- )
72
- updated_target_function: Callable = update_wrapper(target_function, source_function)
73
- updated_target_function.__kwdefaults__ = source_function.__kwdefaults__
74
- return updated_target_function
75
-
76
-
77
- async def get_current_user(
78
- security_scopes: SecurityScopes,
79
- authorization: str = Security(oauth2_scheme),
80
- db: Session = Depends(get_db),
81
- ) -> FidesUser:
82
- """A wrapper around verify_oauth_client that returns that client's user if one exists."""
83
- client = await verify_oauth_client(
84
- security_scopes=security_scopes,
85
- authorization=authorization,
86
- db=db,
87
- )
88
-
89
- if client.id == CONFIG.security.oauth_root_client_id:
90
- return FidesUser(
91
- id=CONFIG.security.oauth_root_client_id,
92
- username=CONFIG.security.root_username,
93
- created_at=datetime.utcnow(),
94
- )
95
-
96
- return client.user # type: ignore[attr-defined]
97
-
98
-
99
- def is_callback_token_expired(issued_at: datetime | None) -> bool:
100
- """Returns True if the token is older than the expiration of the redis cache. We
101
- can't resume executing the privacy request if the identity data is gone.
102
- """
103
- if not issued_at:
104
- return True
105
73
 
106
- return (
107
- datetime.now() - issued_at
108
- ).total_seconds() / 60.0 > CONFIG.execution.privacy_request_delay_timeout
74
+ def is_callback_token_expired(issued_at: datetime) -> bool:
75
+ """Check if a callback token has expired (24 hours)."""
76
+ expiration_time = issued_at + timedelta(hours=24)
77
+ return datetime.now() > expiration_time
109
78
 
110
79
 
111
80
  def _get_webhook_jwe_or_error(
@@ -114,9 +83,13 @@ def _get_webhook_jwe_or_error(
114
83
  if authorization is None:
115
84
  raise AuthenticationError(detail="Authentication Failure")
116
85
 
117
- token_data = json.loads(
118
- extract_payload(authorization, CONFIG.security.app_encryption_key)
119
- )
86
+ try:
87
+ token_data = json.loads(
88
+ extract_payload(authorization, CONFIG.security.app_encryption_key)
89
+ )
90
+ except exceptions.JWEError:
91
+ raise AuthorizationError(detail="Not Authorized for this action")
92
+
120
93
  try:
121
94
  token = WebhookJWE(**token_data)
122
95
  except ValidationError:
@@ -160,6 +133,98 @@ def _get_request_task_jwe_or_error(
160
133
  return token
161
134
 
162
135
 
136
+ def validate_download_token(token: str, privacy_request_id: str) -> DownloadTokenJWE:
137
+ """
138
+ Validate a download token for accessing privacy request packages.
139
+
140
+ Args:
141
+ token: The JWE token to validate
142
+ privacy_request_id: The privacy request ID the token should grant access to
143
+
144
+ Returns:
145
+ The validated DownloadTokenJWE object
146
+
147
+ Raises:
148
+ AuthenticationError: If token is invalid or expired
149
+ AuthorizationError: If token doesn't grant access to the requested privacy request
150
+ """
151
+ if not token:
152
+ raise AuthenticationError(detail="Download token is required")
153
+
154
+ # Check if token looks like a JWE (should have 5 parts separated by dots)
155
+ if token.count(".") != 4:
156
+ raise AuthenticationError(detail="Invalid download token format")
157
+
158
+ try:
159
+ token_data = json.loads(
160
+ extract_payload(token, CONFIG.security.app_encryption_key)
161
+ )
162
+ except exceptions.JWEError:
163
+ raise AuthenticationError(detail="Invalid download token format")
164
+
165
+ try:
166
+ download_token = DownloadTokenJWE(**token_data)
167
+ except ValidationError:
168
+ raise AuthenticationError(detail="Invalid download token structure")
169
+
170
+ # Verify the token grants access to the requested privacy request
171
+ if download_token.privacy_request_id != privacy_request_id:
172
+ raise AuthorizationError(
173
+ detail="Download token does not grant access to this privacy request"
174
+ )
175
+
176
+ # Verify the token has the required scope
177
+ required_scope = "privacy-request-access-results:read"
178
+ if required_scope not in download_token.scopes:
179
+ raise AuthorizationError(detail="Download token lacks required permissions")
180
+
181
+ # Check if the token has expired
182
+ try:
183
+ expiration_time = datetime.fromisoformat(download_token.exp)
184
+ if datetime.now() > expiration_time:
185
+ raise AuthenticationError(detail="Download token has expired")
186
+ except (ValueError, TypeError):
187
+ raise AuthenticationError(detail="Invalid token expiration format")
188
+
189
+ return download_token
190
+
191
+
192
+ def copy_func(source_function: Callable) -> Callable:
193
+ """Based on http://stackoverflow.com/a/6528148/190597 (Glenn Maynard)"""
194
+ target_function = FunctionType(
195
+ source_function.__code__,
196
+ source_function.__globals__,
197
+ name=source_function.__name__,
198
+ argdefs=source_function.__defaults__,
199
+ closure=source_function.__closure__,
200
+ )
201
+ updated_target_function: Callable = update_wrapper(target_function, source_function)
202
+ updated_target_function.__kwdefaults__ = source_function.__kwdefaults__
203
+ return updated_target_function
204
+
205
+
206
+ async def get_current_user(
207
+ security_scopes: SecurityScopes,
208
+ authorization: str = Security(oauth2_scheme),
209
+ db: Session = Depends(get_db),
210
+ ) -> FidesUser:
211
+ """A wrapper around verify_oauth_client that returns that client's user if one exists."""
212
+ client = await verify_oauth_client(
213
+ security_scopes=security_scopes,
214
+ authorization=authorization,
215
+ db=db,
216
+ )
217
+
218
+ if client.id == CONFIG.security.oauth_root_client_id:
219
+ return FidesUser(
220
+ id=CONFIG.security.oauth_root_client_id,
221
+ username=CONFIG.security.root_username,
222
+ created_at=datetime.utcnow(),
223
+ )
224
+
225
+ return client.user # type: ignore[attr-defined]
226
+
227
+
163
228
  def verify_callback_oauth_policy_pre_webhook(
164
229
  security_scopes: SecurityScopes,
165
230
  authorization: str = Security(oauth2_scheme),
@@ -87,6 +87,12 @@ class AdminUIConfig(FidesSchema):
87
87
  model_config = ConfigDict(extra="forbid")
88
88
 
89
89
 
90
+ class PrivacyCenterConfig(FidesSchema):
91
+ url: SerializeAsAny[Optional[AnyHttpUrlStringRemovesSlash]] = None
92
+
93
+ model_config = ConfigDict(extra="forbid")
94
+
95
+
90
96
  class ConsentConfig(FidesSchema):
91
97
  override_vendor_purposes: Optional[bool]
92
98
  model_config = ConfigDict(extra="forbid")
@@ -119,6 +125,7 @@ class ApplicationConfig(FidesSchema):
119
125
  security: Optional[SecurityApplicationConfig] = None
120
126
  consent: Optional[ConsentConfig] = None
121
127
  admin_ui: Optional[AdminUIConfig] = None
128
+ privacy_center: Optional[PrivacyCenterConfig] = None
122
129
 
123
130
  @model_validator(mode="before")
124
131
  @classmethod
@@ -4,6 +4,8 @@ from pydantic import BaseModel, ConfigDict
4
4
 
5
5
  from fides.api.models.connectionconfig import ConnectionType
6
6
  from fides.api.schemas.connection_configuration.enums.system_type import SystemType
7
+ from fides.api.schemas.enums.connection_category import ConnectionCategory
8
+ from fides.api.schemas.enums.integration_feature import IntegrationFeature
7
9
  from fides.api.schemas.policy import ActionType
8
10
 
9
11
 
@@ -19,4 +21,8 @@ class ConnectionSystemTypeMap(BaseModel):
19
21
  authorization_required: Optional[bool] = False
20
22
  user_guide: Optional[str] = None
21
23
  supported_actions: List[ActionType]
24
+ # New fields for enhanced display information
25
+ category: Optional[ConnectionCategory] = None
26
+ tags: Optional[List[str]] = None
27
+ enabled_features: Optional[List[IntegrationFeature]] = None
22
28
  model_config = ConfigDict(use_enum_values=True, from_attributes=True)
File without changes
@@ -0,0 +1,20 @@
1
+ from enum import Enum
2
+
3
+
4
+ class ConnectionCategory(str, Enum):
5
+ """
6
+ Categories for connection types, matching frontend ConnectionCategory enum
7
+ """
8
+
9
+ DATA_CATALOG = "DATA_CATALOG"
10
+ DATA_WAREHOUSE = "DATA_WAREHOUSE"
11
+ DATABASE = "DATABASE"
12
+ IDENTITY_PROVIDER = "IDENTITY_PROVIDER"
13
+ WEBSITE = "WEBSITE"
14
+ CRM = "CRM"
15
+ MANUAL = "MANUAL"
16
+ MARKETING = "MARKETING"
17
+ ANALYTICS = "ANALYTICS"
18
+ ECOMMERCE = "ECOMMERCE"
19
+ COMMUNICATION = "COMMUNICATION"
20
+ CUSTOM = "CUSTOM" # Fallback for uncategorized/custom uploaded integrations
@@ -0,0 +1,23 @@
1
+ from enum import Enum
2
+
3
+
4
+ class IntegrationFeature(str, Enum):
5
+ """
6
+ Features that can be enabled for different integration types.
7
+ These control which tabs and functionality are available in the integration detail view.
8
+ """
9
+
10
+ # Enables data discovery and monitoring functionality - shows "Data discovery" tab
11
+ DATA_DISCOVERY = "DATA_DISCOVERY"
12
+
13
+ # Enables data synchronization to external systems - shows "Data sync" tab
14
+ DATA_SYNC = "DATA_SYNC"
15
+
16
+ # Enables task/workflow management for manual processes - shows "Tasks" tab
17
+ TASKS = "TASKS"
18
+
19
+ # Indicates integration doesn't require connection testing - shows "Details" tab instead of "Connection" tab
20
+ WITHOUT_CONNECTION = "WITHOUT_CONNECTION"
21
+
22
+ # Enables Data Subject Request automation for SAAS integrations
23
+ DSR_AUTOMATION = "DSR_AUTOMATION"
@@ -39,3 +39,12 @@ class RequestTaskJWE(BaseModel):
39
39
  request_task_id: str
40
40
  scopes: List[str]
41
41
  iat: str
42
+
43
+
44
+ class DownloadTokenJWE(BaseModel):
45
+ """Describes JWE that is given to users to access their privacy request download package"""
46
+
47
+ privacy_request_id: str
48
+ scopes: List[str]
49
+ iat: str
50
+ exp: str
@@ -1,3 +1,4 @@
1
+ from abc import ABC
1
2
  from typing import Any, Dict, List, Literal, Optional, Union
2
3
 
3
4
  from pydantic import ConfigDict, Field, field_validator, model_validator
@@ -12,22 +13,10 @@ class CustomIdentity(FidesSchema):
12
13
  label: str
13
14
 
14
15
 
15
- class LocationIdentityField(FidesSchema):
16
- """Location field configuration that extends the useful parts of CustomPrivacyRequestField"""
17
-
18
- label: str
19
- required: Optional[bool] = True
20
- default_value: Optional[str] = None
21
- query_param_key: Optional[str] = None
22
- ip_geolocation_hint: Optional[bool] = False
23
- # Note: We intentionally omit 'hidden' field as it doesn't make sense for location identity input
24
-
25
-
26
16
  class IdentityInputs(FidesSchema):
27
17
  name: Optional[RequiredType] = None
28
18
  email: Optional[RequiredType] = None
29
19
  phone: Optional[RequiredType] = None
30
- location: Optional[Union[RequiredType, LocationIdentityField]] = None
31
20
  model_config = ConfigDict(extra="allow")
32
21
 
33
22
  def __init__(self, **data: Any):
@@ -42,13 +31,12 @@ class IdentityInputs(FidesSchema):
42
31
  f'Custom identity "{field}" must be an instance of CustomIdentity '
43
32
  '(e.g. {"label": "Field label"})'
44
33
  )
45
- elif field == "location" and isinstance(value, dict):
46
- # Handle location field as LocationIdentityField
47
- data[field] = LocationIdentityField(**value)
48
34
  super().__init__(**data)
49
35
 
50
36
 
51
- class CustomPrivacyRequestField(FidesSchema):
37
+ class BaseCustomPrivacyRequestField(FidesSchema, ABC):
38
+ """Abstract base class for all custom privacy request fields"""
39
+
52
40
  label: str
53
41
  required: Optional[bool] = True
54
42
  default_value: Optional[str] = None
@@ -69,6 +57,41 @@ class CustomPrivacyRequestField(FidesSchema):
69
57
  return values
70
58
 
71
59
 
60
+ class CustomPrivacyRequestField(BaseCustomPrivacyRequestField):
61
+ """Regular custom privacy request field supporting text, select, and multiselect types"""
62
+
63
+ field_type: Optional[Literal["text", "select", "multiselect"]] = None
64
+ options: Optional[List[str]] = None
65
+
66
+
67
+ class LocationCustomPrivacyRequestField(BaseCustomPrivacyRequestField):
68
+ """Location field that doesn't support options and includes IP geolocation hint"""
69
+
70
+ field_type: Literal["location"] = "location"
71
+ ip_geolocation_hint: Optional[bool] = False
72
+
73
+ @model_validator(mode="before")
74
+ @classmethod
75
+ def validate_location_field(cls, values: Dict[str, Any]) -> Dict[str, Any]:
76
+ # Ensure options is not provided for location fields
77
+ if "options" in values:
78
+ raise ValueError(
79
+ "LocationCustomPrivacyRequestField does not support options"
80
+ )
81
+
82
+ # This field cannot be hidden
83
+ if values.get("hidden"):
84
+ raise ValueError("Custom location fields cannot be hidden")
85
+
86
+ return values
87
+
88
+
89
+ # Create a simple union type - Pydantic will use the field_type to determine which model to use
90
+ CustomPrivacyRequestFieldUnion = Union[
91
+ LocationCustomPrivacyRequestField, CustomPrivacyRequestField
92
+ ]
93
+
94
+
72
95
  class PrivacyRequestOption(FidesSchema):
73
96
  locations: Optional[Union[List[PrivacyNoticeRegion], Literal["fallback"]]] = None
74
97
  policy_key: Optional[str] = None
@@ -79,7 +102,9 @@ class PrivacyRequestOption(FidesSchema):
79
102
  confirm_button_text: Optional[str] = Field(alias="confirmButtonText", default=None)
80
103
  cancel_button_text: Optional[str] = Field(alias="cancelButtonText", default=None)
81
104
  identity_inputs: Optional[IdentityInputs] = None
82
- custom_privacy_request_fields: Optional[Dict[str, CustomPrivacyRequestField]] = None
105
+ custom_privacy_request_fields: Optional[
106
+ Dict[str, CustomPrivacyRequestFieldUnion]
107
+ ] = None
83
108
 
84
109
 
85
110
  class ConsentConfigButton(FidesSchema):
@@ -89,7 +114,9 @@ class ConsentConfigButton(FidesSchema):
89
114
  cancel_button_text: Optional[str] = Field(alias="cancelButtonText", default=None)
90
115
  icon_path: str
91
116
  identity_inputs: IdentityInputs
92
- custom_privacy_request_fields: Optional[Dict[str, CustomPrivacyRequestField]] = None
117
+ custom_privacy_request_fields: Optional[
118
+ Dict[str, CustomPrivacyRequestFieldUnion]
119
+ ] = None
93
120
  title: str
94
121
  modal_title: Optional[str] = Field(alias="modalTitle", default=None)
95
122
 
@@ -174,7 +201,9 @@ class PartialPrivacyRequestOption(FidesSchema):
174
201
  policy_key: str
175
202
  title: str
176
203
  identity_inputs: Optional[IdentityInputs] = None
177
- custom_privacy_request_fields: Optional[Dict[str, CustomPrivacyRequestField]] = None
204
+ custom_privacy_request_fields: Optional[
205
+ Dict[str, CustomPrivacyRequestFieldUnion]
206
+ ] = None
178
207
 
179
208
 
180
209
  class PartialPrivacyCenterConfig(FidesSchema):
@@ -18,6 +18,7 @@ from fides.api.schemas.user import PrivacyRequestReviewer
18
18
  from fides.api.util.collection_util import Row
19
19
  from fides.api.util.encryption.aes_gcm_encryption_scheme import verify_encryption_key
20
20
  from fides.api.util.enums import ColumnSort
21
+ from fides.api.util.text import normalize_location_code
21
22
  from fides.config import CONFIG
22
23
 
23
24
 
@@ -103,6 +104,7 @@ class PrivacyRequestCreate(FidesSchema):
103
104
  property_id: Optional[str] = None
104
105
  consent_preferences: Optional[List[Consent]] = None # TODO Slated for deprecation
105
106
  source: Optional[PrivacyRequestSource] = None
107
+ location: Optional[str] = None
106
108
 
107
109
  @field_validator("encryption_key")
108
110
  @classmethod
@@ -114,6 +116,18 @@ class PrivacyRequestCreate(FidesSchema):
114
116
  verify_encryption_key(value.encode(CONFIG.security.encoding))
115
117
  return value
116
118
 
119
+ @field_validator("location")
120
+ @classmethod
121
+ def validate_location(
122
+ cls: Type["PrivacyRequestCreate"], value: Optional[str] = None
123
+ ) -> Optional[str]:
124
+ """Validate and normalize location to ISO 3166 format"""
125
+ if value is None:
126
+ return None
127
+
128
+ # nuance here is the validator will coalesce values from the less strict format to ISO 3166 (i.e. "us_ca" -> "US-CA")
129
+ return normalize_location_code(value)
130
+
117
131
 
118
132
  class PrivacyRequestResubmit(PrivacyRequestCreate):
119
133
  """Schema used to copy a privacy request for resubmission"""
@@ -321,6 +335,7 @@ class PrivacyRequestResponse(FidesSchema):
321
335
  custom_privacy_request_fields_approved_by: Optional[str] = None
322
336
  custom_privacy_request_fields_approved_at: Optional[datetime] = None
323
337
  source: Optional[PrivacyRequestSource] = None
338
+ location: Optional[str] = None
324
339
  deleted_at: Optional[datetime] = None
325
340
  deleted_by: Optional[str] = None
326
341
  finalized_at: Optional[datetime] = None
@@ -437,6 +452,7 @@ class PrivacyRequestFilter(FidesSchema):
437
452
  errored_lt: Optional[datetime] = None
438
453
  errored_gt: Optional[datetime] = None
439
454
  external_id: Optional[str] = None
455
+ location: Optional[str] = None
440
456
  action_type: Optional[ActionType] = None
441
457
  verbose: Optional[bool] = False
442
458
  include_identities: Optional[bool] = False
@@ -0,0 +1,19 @@
1
+ from typing import List, Optional
2
+
3
+ from pydantic import BaseModel, ConfigDict
4
+
5
+ from fides.api.schemas.enums.connection_category import ConnectionCategory
6
+ from fides.api.schemas.enums.integration_feature import IntegrationFeature
7
+
8
+
9
+ class SaaSDisplayInfo(BaseModel):
10
+ """
11
+ Optional display information for SAAS integrations to enhance frontend presentation.
12
+ When not provided, smart defaults will be inferred based on the integration type.
13
+ """
14
+
15
+ category: Optional[ConnectionCategory] = None
16
+ tags: Optional[List[str]] = None
17
+ enabled_features: Optional[List[IntegrationFeature]] = None
18
+
19
+ model_config = ConfigDict(use_enum_values=True)
@@ -17,6 +17,7 @@ from fides.api.graph.config import (
17
17
  from fides.api.schemas.base_class import FidesSchema
18
18
  from fides.api.schemas.limiter.rate_limit_config import RateLimitConfig
19
19
  from fides.api.schemas.policy import ActionType
20
+ from fides.api.schemas.saas.display_info import SaaSDisplayInfo
20
21
  from fides.api.schemas.saas.shared_schemas import HTTPMethod
21
22
  from fides.api.service.saas_request.saas_request_override_factory import (
22
23
  SaaSRequestOverrideFactory,
@@ -428,6 +429,7 @@ class SaaSConfig(SaaSConfigBase):
428
429
  rate_limit_config: Optional[RateLimitConfig] = None
429
430
  consent_requests: Optional[ConsentRequestMap] = None
430
431
  user_guide: Optional[str] = None
432
+ display_info: Optional[SaaSDisplayInfo] = None
431
433
 
432
434
  @property
433
435
  def top_level_endpoint_dict(self) -> Dict[str, Endpoint]:
@@ -37,6 +37,8 @@ class StorageDetails(Enum):
37
37
  NAMING = "naming"
38
38
  MAX_RETRIES = "max_retries"
39
39
  AUTH_METHOD = "auth_method"
40
+ ENABLE_STREAMING = "enable_streaming"
41
+ ENABLE_ACCESS_PACKAGE_REDIRECT = "enable_access_package_redirect"
40
42
  model_config = ConfigDict(extra="forbid")
41
43
 
42
44
 
@@ -58,6 +60,8 @@ class StorageDetailsS3(FileBasedStorageDetails):
58
60
  auth_method: AWSAuthMethod
59
61
  bucket: str
60
62
  max_retries: Optional[int] = 0
63
+ enable_streaming: Optional[bool] = False
64
+ enable_access_package_redirect: Optional[bool] = False
61
65
  model_config = ConfigDict(use_enum_values=True)
62
66
 
63
67
 
File without changes
@@ -0,0 +1,75 @@
1
+ from loguru import logger
2
+ from sqlalchemy.orm import Session
3
+
4
+ from fides.api.common_exceptions import PrivacyRequestError
5
+ from fides.api.models.connectionconfig import ConnectionConfig
6
+ from fides.api.models.datasetconfig import DatasetConfig
7
+ from fides.api.models.privacy_request import PrivacyRequest, RequestTask
8
+ from fides.api.schemas.privacy_request import PrivacyRequestStatus
9
+ from fides.api.task.task_resources import TaskResources
10
+
11
+
12
+ def requeue_polling_request(
13
+ db: Session,
14
+ async_task: RequestTask,
15
+ ) -> None:
16
+ """Re-queue a Privacy request that polls async tasks for a given privacy request"""
17
+ # Check that the privacy request is approved or in processing
18
+ privacy_request: PrivacyRequest = async_task.privacy_request
19
+
20
+ if privacy_request.status not in [
21
+ PrivacyRequestStatus.approved,
22
+ PrivacyRequestStatus.in_processing,
23
+ ]:
24
+ raise PrivacyRequestError(
25
+ f"Cannot re-queue privacy request {privacy_request.id} with status {privacy_request.status.value}"
26
+ )
27
+
28
+ logger.info(
29
+ "Polling starting for {} task {} {}",
30
+ async_task.action_type,
31
+ async_task.collection_address,
32
+ async_task.id,
33
+ )
34
+
35
+ connection_config = get_connection_config_from_task(db, async_task)
36
+
37
+ with TaskResources(
38
+ privacy_request,
39
+ privacy_request.policy,
40
+ [connection_config],
41
+ async_task,
42
+ db,
43
+ ) as resources:
44
+ # graph_task: GraphTask = create_graph_task(db, async_task, resources)
45
+ # Currently, upstream tasks and "input keys" (which are built by data dependencies)
46
+ # are the same, but they may not be the same in the future.
47
+ # upstream_tasks = async_task.upstream_tasks_objects(db)
48
+ # upstream_access_data: List[List[Row]] = _build_upstream_access_data(
49
+ # graph_task.execution_node.input_keys, upstream_tasks
50
+ # )
51
+ # TODO: Implement the polling strategy
52
+ logger.info(f"found resources: {resources}")
53
+ return None
54
+
55
+
56
+ def get_connection_config_from_task(
57
+ db: Session, request_task: RequestTask
58
+ ) -> ConnectionConfig:
59
+ dataset_config = DatasetConfig.filter(
60
+ db=db,
61
+ conditions=(DatasetConfig.fides_key == request_task.dataset_name),
62
+ ).first()
63
+ if not dataset_config:
64
+ raise PrivacyRequestError(
65
+ f"DatasetConfig with fides_key {request_task.dataset_name} not found."
66
+ )
67
+ connection_config = ConnectionConfig.get(
68
+ db=db, object_id=dataset_config.connection_config_id
69
+ )
70
+ if not connection_config:
71
+ raise PrivacyRequestError(
72
+ f"ConnectionConfig with id {dataset_config.connection_config_id} not found."
73
+ )
74
+
75
+ return connection_config
@@ -11,7 +11,7 @@ from sqlalchemy.orm import Session
11
11
  from starlette.status import HTTP_204_NO_CONTENT
12
12
 
13
13
  from fides.api.common_exceptions import (
14
- AwaitingAsyncTaskCallback,
14
+ AwaitingAsyncTask,
15
15
  FidesopsException,
16
16
  PostProcessingException,
17
17
  SkippingConsentPropagation,
@@ -229,7 +229,6 @@ class SaaSConnector(BaseConnector[AuthenticatedClient], Contextualizable):
229
229
  query_config: SaaSQueryConfig = self.query_config(node)
230
230
 
231
231
  # generate initial set of requests if read request is defined, otherwise raise an exception
232
-
233
232
  # An endpoint can be defined with multiple 'read' requests if the data for a single
234
233
  # collection can be accessed in multiple ways for example:
235
234
  #
@@ -336,8 +335,8 @@ class SaaSConnector(BaseConnector[AuthenticatedClient], Contextualizable):
336
335
  if awaiting_async_callback:
337
336
  # If a read request was marked to expect async results, original response data here is ignored.
338
337
  # We'll instead use the data received in the callback URL later.
339
- # Raising an AwaitingAsyncTaskCallback to put this task in an awaiting_processing state
340
- raise AwaitingAsyncTaskCallback()
338
+ # Raising an AwaitingAsyncTask to put this task in an awaiting_processing state
339
+ raise AwaitingAsyncTask()
341
340
 
342
341
  return rows
343
342
 
@@ -641,8 +640,8 @@ class SaaSConnector(BaseConnector[AuthenticatedClient], Contextualizable):
641
640
  if awaiting_async_callback:
642
641
  # Asynchronous masking request detected in saas config.
643
642
  # If the masking request was marked to expect async results, original responses are ignored
644
- # and we raise an AwaitingAsyncTaskCallback to put this task in an awaiting_processing state.
645
- raise AwaitingAsyncTaskCallback()
643
+ # and we raise an AwaitingAsyncTask to put this task in an awaiting_processing state.
644
+ raise AwaitingAsyncTask()
646
645
  return rows_updated
647
646
 
648
647
  @staticmethod