ethyca-fides 2.63.3rc0__py2.py3-none-any.whl → 2.64.1b0__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.
Files changed (362) hide show
  1. {ethyca_fides-2.63.3rc0.dist-info → ethyca_fides-2.64.1b0.dist-info}/METADATA +2 -2
  2. {ethyca_fides-2.63.3rc0.dist-info → ethyca_fides-2.64.1b0.dist-info}/RECORD +249 -242
  3. fides/_version.py +3 -3
  4. fides/api/alembic/migrations/versions/ba414a58ba90_create_manual_task_config_tables.py +121 -0
  5. fides/api/api/v1/endpoints/connection_endpoints.py +16 -3
  6. fides/api/api/v1/endpoints/oauth_endpoints.py +8 -2
  7. fides/api/db/base.py +4 -0
  8. fides/api/models/attachment.py +37 -23
  9. fides/api/models/manual_tasks/__init__.py +6 -0
  10. fides/api/models/manual_tasks/manual_task.py +11 -1
  11. fides/api/models/manual_tasks/manual_task_config.py +136 -0
  12. fides/api/models/manual_tasks/manual_task_log.py +13 -9
  13. fides/api/schemas/connection_configuration/connection_config.py +19 -4
  14. fides/api/schemas/manual_tasks/manual_task_config.py +311 -0
  15. fides/api/schemas/manual_tasks/manual_task_schemas.py +1 -1
  16. fides/api/schemas/manual_tasks/manual_task_status.py +1 -1
  17. fides/api/schemas/privacy_request.py +2 -0
  18. fides/api/service/connectors/query_configs/saas_query_config.py +15 -0
  19. fides/api/service/privacy_request/attachment_handling.py +132 -0
  20. fides/api/service/privacy_request/dsr_package/dsr_report_builder.py +264 -46
  21. fides/api/service/privacy_request/dsr_package/templates/attachments_index.html +33 -0
  22. fides/api/service/privacy_request/dsr_package/templates/collection_index.html +34 -9
  23. fides/api/service/privacy_request/dsr_package/templates/main.css +45 -2
  24. fides/api/service/privacy_request/dsr_package/templates/welcome.html +12 -8
  25. fides/api/service/privacy_request/request_runner_service.py +258 -139
  26. fides/api/service/storage/gcs.py +15 -3
  27. fides/api/service/storage/s3.py +28 -14
  28. fides/api/service/storage/util.py +45 -7
  29. fides/api/tasks/csv_utils.py +170 -0
  30. fides/api/tasks/encryption_utils.py +42 -0
  31. fides/api/tasks/storage.py +85 -91
  32. fides/api/util/cache.py +6 -3
  33. fides/api/util/saas_util.py +1 -0
  34. fides/config/redis_settings.py +105 -44
  35. fides/service/manual_tasks/manual_task_config_service.py +370 -0
  36. fides/service/manual_tasks/manual_task_service.py +231 -87
  37. fides/service/manual_tasks/utils.py +185 -0
  38. fides/ui-build/static/admin/404.html +1 -1
  39. fides/ui-build/static/admin/_next/static/chunks/1040-630c7f4284dc6f70.js +1 -0
  40. fides/ui-build/static/admin/_next/static/chunks/1100-d43cb04522a6505c.js +1 -0
  41. fides/ui-build/static/admin/_next/static/chunks/1316-6cc72a45ebf7ff81.js +1 -0
  42. fides/ui-build/static/admin/_next/static/chunks/1817-b4688ba5042ec687.js +1 -0
  43. fides/ui-build/static/admin/_next/static/chunks/2430-b480401d44c55416.js +1 -0
  44. fides/ui-build/static/admin/_next/static/chunks/2599-6c4d22e75028d8b6.js +1 -0
  45. fides/ui-build/static/admin/_next/static/chunks/2921-aabf41bf3d7573f9.js +1 -0
  46. fides/ui-build/static/admin/_next/static/chunks/3450-bdaeb35442d810b4.js +1 -0
  47. fides/ui-build/static/admin/_next/static/chunks/3505-a79256cd851dfab4.js +1 -0
  48. fides/ui-build/static/admin/_next/static/chunks/3513-8677ee280eaef0da.js +1 -0
  49. fides/ui-build/static/admin/_next/static/chunks/3855-0dec3e7d9e886550.js +1 -0
  50. fides/ui-build/static/admin/_next/static/chunks/3872-ffa16c2df7ef0ab6.js +1 -0
  51. fides/ui-build/static/admin/_next/static/chunks/3923-5d580fbb1dd6ae01.js +1 -0
  52. fides/ui-build/static/admin/_next/static/chunks/401-fceaae662cfca5a5.js +1 -0
  53. fides/ui-build/static/admin/_next/static/chunks/4060-71cd041e5a57ca5a.js +1 -0
  54. fides/ui-build/static/admin/_next/static/chunks/409-037cfc3f096150f0.js +1 -0
  55. fides/ui-build/static/admin/_next/static/chunks/4121-78a76e980acbd539.js +1 -0
  56. fides/ui-build/static/admin/_next/static/chunks/4230-1cdb7ea1be370ed3.js +1 -0
  57. fides/ui-build/static/admin/_next/static/chunks/431-f72599f01b98f07d.js +1 -0
  58. fides/ui-build/static/admin/_next/static/chunks/4481-f597a7cf03f8c9e1.js +1 -0
  59. fides/ui-build/static/admin/_next/static/chunks/5309-4511df9708d5a63c.js +1 -0
  60. fides/ui-build/static/admin/_next/static/chunks/5574-3cd33b3a6c937899.js +1 -0
  61. fides/ui-build/static/admin/_next/static/chunks/6277-3fb4c7fc790a6d20.js +1 -0
  62. fides/ui-build/static/admin/_next/static/chunks/6662-cb11881dcaabe5e2.js +1 -0
  63. fides/ui-build/static/admin/_next/static/chunks/6853-a4097260e402980e.js +1 -0
  64. fides/ui-build/static/admin/_next/static/chunks/6882-3cc73d407a088d7d.js +1 -0
  65. fides/ui-build/static/admin/_next/static/chunks/69-6889d6674c95e7b5.js +1 -0
  66. fides/ui-build/static/admin/_next/static/chunks/6954-13a25cef3a8fdd76.js +1 -0
  67. fides/ui-build/static/admin/_next/static/chunks/699-8ca44b0de9fa20f0.js +1 -0
  68. fides/ui-build/static/admin/_next/static/chunks/7553-a95939c32d54b5b7.js +1 -0
  69. fides/ui-build/static/admin/_next/static/chunks/79-5670e31eb65d0a53.js +1 -0
  70. fides/ui-build/static/admin/_next/static/chunks/796-9a6b13c838e25538.js +1 -0
  71. fides/ui-build/static/admin/_next/static/chunks/8433-adb1fcb29d82f1b7.js +1 -0
  72. fides/ui-build/static/admin/_next/static/chunks/9046-fdf53cc7e926a8c1.js +1 -0
  73. fides/ui-build/static/admin/_next/static/chunks/{905-8ab919e7b274ed50.js → 905-742074a074be1055.js} +2 -2
  74. fides/ui-build/static/admin/_next/static/chunks/9226-ba6587e46ec7659a.js +1 -0
  75. fides/ui-build/static/admin/_next/static/chunks/{9392.81edc11e3a175275.js → 9392.25024e070026343d.js} +1 -1
  76. fides/ui-build/static/admin/_next/static/chunks/9676.e60a53f1f5890847.js +1 -0
  77. fides/ui-build/static/admin/_next/static/chunks/9767-e49b065d03ce4e80.js +1 -0
  78. fides/ui-build/static/admin/_next/static/chunks/9951-f9ab5cac7e2c05ab.js +1 -0
  79. fides/ui-build/static/admin/_next/static/chunks/pages/404-ac2f0844e5c4b4cd.js +1 -0
  80. fides/ui-build/static/admin/_next/static/chunks/pages/{_app-f70bffa5a7903c46.js → _app-8ec6e466f3373ac0.js} +10 -10
  81. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/manual-0a5f2310ce6b1059.js +1 -0
  82. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/multiple-00cb904825aad7e3.js +1 -0
  83. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems-587e21d14e0a5196.js +1 -0
  84. fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure/add-vendors-fa7305b88c1afd20.js +1 -0
  85. fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure-f140ec9d8e8a0f7a.js +1 -0
  86. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/[id]-0edb7c92518e7d21.js +1 -0
  87. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience-d8d926f0735a2546.js +1 -0
  88. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/[id]-5c949f2e3cef2398.js +1 -0
  89. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/new-130155cfb4a0bcc7.js +1 -0
  90. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices-1135ad8924d32c36.js +1 -0
  91. fides/ui-build/static/admin/_next/static/chunks/pages/consent/properties-776855e370414beb.js +1 -0
  92. fides/ui-build/static/admin/_next/static/chunks/pages/consent/reporting-21c23f75ff1135d9.js +1 -0
  93. fides/ui-build/static/admin/_next/static/chunks/pages/consent-4d5ea70a77df1bb8.js +1 -0
  94. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]/{[resourceUrn]-18e3faf7963962e4.js → [resourceUrn]-c623d6f1a61c8ea9.js} +1 -1
  95. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]-030ee304cbe5e530.js +1 -0
  96. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects-cfac259a30641e68.js +1 -0
  97. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/resources/{[resourceUrn]-7320524a47104798.js → [resourceUrn]-57bd5cdf784f059f.js} +1 -1
  98. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog-7b5aec33da578745.js +1 -0
  99. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-c948f93c833d4358.js +1 -0
  100. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]-333f53caab751428.js +1 -0
  101. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-27205f8457a1ecb0.js +1 -0
  102. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/activity-20a1043f6a06198f.js +1 -0
  103. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/detection/{[resourceUrn]-4c526db0c30c488a.js → [resourceUrn]-06edce289876dea1.js} +1 -1
  104. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{detection-6f27dbb7c8edc69d.js → detection-faf326a6200637d0.js} +1 -1
  105. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/discovery/{[resourceUrn]-562d2b8ae90dd1f0.js → [resourceUrn]-64acf269256ee74f.js} +1 -1
  106. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{discovery-fe7f51502eda57c9.js → discovery-8c3e4be6d36da66d.js} +1 -1
  107. fides/ui-build/static/admin/_next/static/chunks/pages/datamap-fb50de22f83edd4a.js +1 -0
  108. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/[...subfieldNames]-41ab27c4195cfa93.js +1 -0
  109. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]-6e2caba24b3e78c2.js +1 -0
  110. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]-904d43e31157aa55.js +1 -0
  111. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/new-d4e31a1c4a58800e.js +1 -0
  112. fides/ui-build/static/admin/_next/static/chunks/pages/dataset-8f7d16bc5e9229c8.js +1 -0
  113. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/[id]-4a33dd0371dbaebc.js +1 -0
  114. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/new-e88509346b2d2851.js +1 -0
  115. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection-8f9b8890018e1ea5.js +1 -0
  116. fides/ui-build/static/admin/_next/static/chunks/pages/{fides-js-docs-80b241bf6cddb72e.js → fides-js-docs-5d8fd1af75f19e2f.js} +1 -1
  117. fides/ui-build/static/admin/_next/static/chunks/pages/index-1adb6bcb71701ac2.js +1 -0
  118. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-fdc2964fa7d1d8fd.js +1 -0
  119. fides/ui-build/static/admin/_next/static/chunks/pages/integrations-adc286ff254e7f41.js +1 -0
  120. fides/ui-build/static/admin/_next/static/chunks/pages/messaging/[id]-9b4d1d61c7c97509.js +1 -0
  121. fides/ui-build/static/admin/_next/static/chunks/pages/messaging/add-template-f8fd4795e260887c.js +1 -0
  122. fides/ui-build/static/admin/_next/static/chunks/pages/messaging-aa744ae8b61e5ff2.js +1 -0
  123. fides/ui-build/static/admin/_next/static/chunks/pages/poc/ant-components-3407158757fb3627.js +1 -0
  124. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/AntForm-47e947c02ae90fd0.js +1 -0
  125. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/FormikAntFormItem-24f9a44512ce8827.js +1 -0
  126. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/FormikControlled-e567a69f8c37fb9a.js +1 -0
  127. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/FormikField-35a33f9c7def2220.js +1 -0
  128. fides/ui-build/static/admin/_next/static/chunks/pages/poc/forms-780e18dde8e38099.js +1 -0
  129. fides/ui-build/static/admin/_next/static/chunks/pages/poc/table-migration-7a17dffa515e5560.js +1 -0
  130. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-91dd0039cc2b70bc.js +1 -0
  131. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-b01cbbaac34dadbc.js +1 -0
  132. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-a15410de7f1d0f84.js +1 -0
  133. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure-1a1aa83a3f88844c.js +1 -0
  134. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-c4e1b69fb5bab61a.js +1 -0
  135. fides/ui-build/static/admin/_next/static/chunks/pages/properties/[id]-19737d4f21aadbee.js +1 -0
  136. fides/ui-build/static/admin/_next/static/chunks/pages/properties/add-property-9ccb295110feee20.js +1 -0
  137. fides/ui-build/static/admin/_next/static/chunks/pages/properties-3a1037a2e036212a.js +1 -0
  138. fides/ui-build/static/admin/_next/static/chunks/pages/reporting/datamap-4cdbbb8cd1d8698e.js +1 -0
  139. fides/ui-build/static/admin/_next/static/chunks/pages/settings/about/alpha-965cc21889b25e44.js +1 -0
  140. fides/ui-build/static/admin/_next/static/chunks/pages/settings/about-0e1c381d488a7ada.js +1 -0
  141. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent/[configuration_id]/[purpose_id]-d0e350d2a2667883.js +1 -0
  142. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-7796fbf458f8f159.js +1 -0
  143. fides/ui-build/static/admin/_next/static/chunks/pages/settings/custom-fields-6f866bc799a5f67f.js +1 -0
  144. fides/ui-build/static/admin/_next/static/chunks/pages/settings/domain-records-0b44b2b224077dcd.js +1 -0
  145. fides/ui-build/static/admin/_next/static/chunks/pages/settings/domains-5d00e1155bd11178.js +1 -0
  146. fides/ui-build/static/admin/_next/static/chunks/pages/settings/email-templates-d2cdbe770683e9df.js +1 -0
  147. fides/ui-build/static/admin/_next/static/chunks/pages/settings/locations-811dadb489f23d7d.js +1 -0
  148. fides/ui-build/static/admin/_next/static/chunks/pages/settings/organization-24108f615ff5e1e7.js +1 -0
  149. fides/ui-build/static/admin/_next/static/chunks/pages/settings/regulations-54f142bc3e4c95ba.js +1 -0
  150. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/test-datasets-fef247a87baeb080.js +1 -0
  151. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]-6eb886e7b7e6785b.js +1 -0
  152. fides/ui-build/static/admin/_next/static/chunks/pages/systems-7b71274334c559a4.js +1 -0
  153. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-18534d2a79a3850b.js +1 -0
  154. fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/[id]-75d41fde668b9025.js +1 -0
  155. fides/ui-build/static/admin/_next/static/chunks/pages/user-management-dd43755b687c09a7.js +1 -0
  156. fides/ui-build/static/admin/_next/static/chunks/webpack-0a61b5bd21a41fe6.js +1 -0
  157. fides/ui-build/static/admin/_next/static/css/c693338e3bc8dcc6.css +1 -0
  158. fides/ui-build/static/admin/_next/static/nRQ3pmK_d3F5PJE39rP2h/_buildManifest.js +1 -0
  159. fides/ui-build/static/admin/add-systems/manual.html +1 -1
  160. fides/ui-build/static/admin/add-systems/multiple.html +1 -1
  161. fides/ui-build/static/admin/add-systems.html +1 -1
  162. fides/ui-build/static/admin/consent/configure/add-vendors.html +1 -1
  163. fides/ui-build/static/admin/consent/configure.html +1 -1
  164. fides/ui-build/static/admin/consent/privacy-experience/[id].html +1 -1
  165. fides/ui-build/static/admin/consent/privacy-experience/new.html +1 -1
  166. fides/ui-build/static/admin/consent/privacy-experience.html +1 -1
  167. fides/ui-build/static/admin/consent/privacy-notices/[id].html +1 -1
  168. fides/ui-build/static/admin/consent/privacy-notices/new.html +1 -1
  169. fides/ui-build/static/admin/consent/privacy-notices.html +1 -1
  170. fides/ui-build/static/admin/consent/properties.html +1 -1
  171. fides/ui-build/static/admin/consent/reporting.html +1 -1
  172. fides/ui-build/static/admin/consent.html +1 -1
  173. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn].html +1 -1
  174. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn].html +1 -1
  175. fides/ui-build/static/admin/data-catalog/[systemId]/projects.html +1 -1
  176. fides/ui-build/static/admin/data-catalog/[systemId]/resources/[resourceUrn].html +1 -1
  177. fides/ui-build/static/admin/data-catalog/[systemId]/resources.html +1 -1
  178. fides/ui-build/static/admin/data-catalog.html +1 -1
  179. fides/ui-build/static/admin/data-discovery/action-center/[monitorId]/[systemId].html +1 -1
  180. fides/ui-build/static/admin/data-discovery/action-center/[monitorId].html +1 -1
  181. fides/ui-build/static/admin/data-discovery/action-center.html +1 -1
  182. fides/ui-build/static/admin/data-discovery/activity.html +1 -1
  183. fides/ui-build/static/admin/data-discovery/detection/[resourceUrn].html +1 -1
  184. fides/ui-build/static/admin/data-discovery/detection.html +1 -1
  185. fides/ui-build/static/admin/data-discovery/discovery/[resourceUrn].html +1 -1
  186. fides/ui-build/static/admin/data-discovery/discovery.html +1 -1
  187. fides/ui-build/static/admin/datamap.html +1 -1
  188. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName]/[...subfieldNames].html +1 -1
  189. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName].html +1 -1
  190. fides/ui-build/static/admin/dataset/[datasetId].html +1 -1
  191. fides/ui-build/static/admin/dataset/new.html +1 -1
  192. fides/ui-build/static/admin/dataset.html +1 -1
  193. fides/ui-build/static/admin/datastore-connection/[id].html +1 -1
  194. fides/ui-build/static/admin/datastore-connection/new.html +1 -1
  195. fides/ui-build/static/admin/datastore-connection.html +1 -1
  196. fides/ui-build/static/admin/images/connector-logos/salesforce.svg +41 -0
  197. fides/ui-build/static/admin/index.html +1 -1
  198. fides/ui-build/static/admin/integrations/[id].html +1 -1
  199. fides/ui-build/static/admin/integrations.html +1 -1
  200. fides/ui-build/static/admin/lib/fides-ext-gpp.js +1 -1
  201. fides/ui-build/static/admin/lib/fides-headless.js +1 -1
  202. fides/ui-build/static/admin/lib/fides-preview.js +1 -1
  203. fides/ui-build/static/admin/lib/fides-tcf.js +2 -2
  204. fides/ui-build/static/admin/lib/fides.js +2 -2
  205. fides/ui-build/static/admin/login/[provider].html +1 -1
  206. fides/ui-build/static/admin/login.html +1 -1
  207. fides/ui-build/static/admin/messaging/[id].html +1 -1
  208. fides/ui-build/static/admin/messaging/add-template.html +1 -1
  209. fides/ui-build/static/admin/messaging.html +1 -1
  210. fides/ui-build/static/admin/poc/ant-components.html +1 -1
  211. fides/ui-build/static/admin/poc/form-experiments/AntForm.html +1 -1
  212. fides/ui-build/static/admin/poc/form-experiments/FormikAntFormItem.html +1 -1
  213. fides/ui-build/static/admin/poc/form-experiments/FormikControlled.html +1 -1
  214. fides/ui-build/static/admin/poc/form-experiments/FormikField.html +1 -1
  215. fides/ui-build/static/admin/poc/form-experiments/FormikSpreadField.html +1 -1
  216. fides/ui-build/static/admin/poc/forms.html +1 -1
  217. fides/ui-build/static/admin/poc/table-migration.html +1 -1
  218. fides/ui-build/static/admin/privacy-requests/[id].html +1 -1
  219. fides/ui-build/static/admin/privacy-requests/configure/messaging.html +1 -1
  220. fides/ui-build/static/admin/privacy-requests/configure/storage.html +1 -1
  221. fides/ui-build/static/admin/privacy-requests/configure.html +1 -1
  222. fides/ui-build/static/admin/privacy-requests.html +1 -1
  223. fides/ui-build/static/admin/properties/[id].html +1 -1
  224. fides/ui-build/static/admin/properties/add-property.html +1 -1
  225. fides/ui-build/static/admin/properties.html +1 -1
  226. fides/ui-build/static/admin/reporting/datamap.html +1 -1
  227. fides/ui-build/static/admin/settings/about/alpha.html +1 -1
  228. fides/ui-build/static/admin/settings/about.html +1 -1
  229. fides/ui-build/static/admin/settings/consent/[configuration_id]/[purpose_id].html +1 -1
  230. fides/ui-build/static/admin/settings/consent.html +1 -1
  231. fides/ui-build/static/admin/settings/custom-fields.html +1 -1
  232. fides/ui-build/static/admin/settings/domain-records.html +1 -1
  233. fides/ui-build/static/admin/settings/domains.html +1 -1
  234. fides/ui-build/static/admin/settings/email-templates.html +1 -1
  235. fides/ui-build/static/admin/settings/locations.html +1 -1
  236. fides/ui-build/static/admin/settings/organization.html +1 -1
  237. fides/ui-build/static/admin/settings/regulations.html +1 -1
  238. fides/ui-build/static/admin/systems/configure/[id]/test-datasets.html +1 -1
  239. fides/ui-build/static/admin/systems/configure/[id].html +1 -1
  240. fides/ui-build/static/admin/systems.html +1 -1
  241. fides/ui-build/static/admin/taxonomy.html +1 -1
  242. fides/ui-build/static/admin/user-management/new.html +1 -1
  243. fides/ui-build/static/admin/user-management/profile/[id].html +1 -1
  244. fides/ui-build/static/admin/user-management.html +1 -1
  245. fides/api/service/privacy_request/dsr_package/templates/item.html +0 -37
  246. fides/ui-build/static/admin/_next/static/chunks/1099-667e84655846e78c.js +0 -1
  247. fides/ui-build/static/admin/_next/static/chunks/1100-0b01f500b1eaf60d.js +0 -1
  248. fides/ui-build/static/admin/_next/static/chunks/1817-951f58ddd5d46081.js +0 -1
  249. fides/ui-build/static/admin/_next/static/chunks/1904-964f8eb328dc2715.js +0 -1
  250. fides/ui-build/static/admin/_next/static/chunks/2310-744354001d01f366.js +0 -1
  251. fides/ui-build/static/admin/_next/static/chunks/2921-49af55ad7c631c93.js +0 -1
  252. fides/ui-build/static/admin/_next/static/chunks/3119-e36ae5071c8f27a5.js +0 -1
  253. fides/ui-build/static/admin/_next/static/chunks/3505-113f9c95d34b7aae.js +0 -1
  254. fides/ui-build/static/admin/_next/static/chunks/3513-5c2d412a84a78971.js +0 -1
  255. fides/ui-build/static/admin/_next/static/chunks/3872-45cc725e241211f0.js +0 -1
  256. fides/ui-build/static/admin/_next/static/chunks/3923-b4f701ada3ef0ee0.js +0 -1
  257. fides/ui-build/static/admin/_next/static/chunks/401-7e800aed05537126.js +0 -1
  258. fides/ui-build/static/admin/_next/static/chunks/4060-90a52a9afc655bfc.js +0 -1
  259. fides/ui-build/static/admin/_next/static/chunks/4121-66b0e00d5e7ae817.js +0 -1
  260. fides/ui-build/static/admin/_next/static/chunks/4132-9b1731bfec6ee537.js +0 -1
  261. fides/ui-build/static/admin/_next/static/chunks/4481-7f6710c928bb0cb0.js +0 -1
  262. fides/ui-build/static/admin/_next/static/chunks/5258-2079138c8cc34f6c.js +0 -1
  263. fides/ui-build/static/admin/_next/static/chunks/5404-2694509cf5fa96da.js +0 -1
  264. fides/ui-build/static/admin/_next/static/chunks/5487-2cbd8d2169eb2a65.js +0 -1
  265. fides/ui-build/static/admin/_next/static/chunks/5683-37137111b3e769fb.js +0 -1
  266. fides/ui-build/static/admin/_next/static/chunks/6202-081545c7822d09af.js +0 -1
  267. fides/ui-build/static/admin/_next/static/chunks/6277-459e054b2702c60e.js +0 -1
  268. fides/ui-build/static/admin/_next/static/chunks/641-7e4eef3222cbda70.js +0 -1
  269. fides/ui-build/static/admin/_next/static/chunks/6853-688df0b88fe65fd5.js +0 -1
  270. fides/ui-build/static/admin/_next/static/chunks/69-00cba94689b9e740.js +0 -1
  271. fides/ui-build/static/admin/_next/static/chunks/6954-4e313b4599b8763d.js +0 -1
  272. fides/ui-build/static/admin/_next/static/chunks/7553-08bc3d9f66695111.js +0 -1
  273. fides/ui-build/static/admin/_next/static/chunks/79-fc548561beed136f.js +0 -1
  274. fides/ui-build/static/admin/_next/static/chunks/796-d6586308ed44334b.js +0 -1
  275. fides/ui-build/static/admin/_next/static/chunks/7980-736f9fd1e749ddd2.js +0 -1
  276. fides/ui-build/static/admin/_next/static/chunks/8032-74d94f7bd5b81c89.js +0 -1
  277. fides/ui-build/static/admin/_next/static/chunks/8433-51870336908fb253.js +0 -1
  278. fides/ui-build/static/admin/_next/static/chunks/8499-1fd392d0be9e8ee4.js +0 -1
  279. fides/ui-build/static/admin/_next/static/chunks/8702-d1c8296f9f6afc10.js +0 -1
  280. fides/ui-build/static/admin/_next/static/chunks/9033-fdd87182c15b91e2.js +0 -1
  281. fides/ui-build/static/admin/_next/static/chunks/9187-851756440f79cd75.js +0 -1
  282. fides/ui-build/static/admin/_next/static/chunks/9327-6a53461c9764b16f.js +0 -1
  283. fides/ui-build/static/admin/_next/static/chunks/9494-1ffb888b95289891.js +0 -1
  284. fides/ui-build/static/admin/_next/static/chunks/9676.61cf5f6d6a083175.js +0 -1
  285. fides/ui-build/static/admin/_next/static/chunks/9767-afd674014a1d1152.js +0 -1
  286. fides/ui-build/static/admin/_next/static/chunks/pages/404-ec04f826f3dd79ea.js +0 -1
  287. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/manual-1bec086d567aacff.js +0 -1
  288. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/multiple-f68bf100e4e60e88.js +0 -1
  289. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems-effde5cfe49de55f.js +0 -1
  290. fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure/add-vendors-ec95ed8cb0712828.js +0 -1
  291. fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure-4cc195e15e0c3cc8.js +0 -1
  292. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/[id]-be8972c79fb39705.js +0 -1
  293. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience-ccf96207de3b74ea.js +0 -1
  294. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/[id]-b9823cc008372cee.js +0 -1
  295. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/new-373f5772ab41bc93.js +0 -1
  296. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices-b9beeee1bde5ca79.js +0 -1
  297. fides/ui-build/static/admin/_next/static/chunks/pages/consent/properties-6ab3a5baafebd199.js +0 -1
  298. fides/ui-build/static/admin/_next/static/chunks/pages/consent/reporting-8562790ae07f17c9.js +0 -1
  299. fides/ui-build/static/admin/_next/static/chunks/pages/consent-42d4d2d6e0253671.js +0 -1
  300. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]-9d1df6d890671b0c.js +0 -1
  301. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects-7eb08af333baaa8e.js +0 -1
  302. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog-bb57eed84f59a932.js +0 -1
  303. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-47eb34aef3e31ac6.js +0 -1
  304. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]-76cefefc53e84c7f.js +0 -1
  305. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-9d8e84a8b4bf568d.js +0 -1
  306. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/activity-f208fef5e72dafd6.js +0 -1
  307. fides/ui-build/static/admin/_next/static/chunks/pages/datamap-db45aa864e9dda8a.js +0 -1
  308. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/[...subfieldNames]-d5cfdebc74654337.js +0 -1
  309. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]-618b89228f83435e.js +0 -1
  310. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]-12fc86f15a4c764e.js +0 -1
  311. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/new-c23d18a9b56c2e3c.js +0 -1
  312. fides/ui-build/static/admin/_next/static/chunks/pages/dataset-e3b2d8e3980ab093.js +0 -1
  313. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/[id]-6e27257eccf65f01.js +0 -1
  314. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/new-bbac1f624424282d.js +0 -1
  315. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection-84eb56f5a07bdf4f.js +0 -1
  316. fides/ui-build/static/admin/_next/static/chunks/pages/index-773182b5e35d0045.js +0 -1
  317. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-eb28c927da5bd653.js +0 -1
  318. fides/ui-build/static/admin/_next/static/chunks/pages/integrations-781808bca01f8048.js +0 -1
  319. fides/ui-build/static/admin/_next/static/chunks/pages/messaging/[id]-b51bee8680d66b20.js +0 -1
  320. fides/ui-build/static/admin/_next/static/chunks/pages/messaging/add-template-1de479533f733fbd.js +0 -1
  321. fides/ui-build/static/admin/_next/static/chunks/pages/messaging-7dc295b3ed3d2224.js +0 -1
  322. fides/ui-build/static/admin/_next/static/chunks/pages/poc/ant-components-f64dac3392f5ded7.js +0 -1
  323. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/AntForm-eb020bfac4bee532.js +0 -1
  324. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/FormikAntFormItem-0bd62e28b539e114.js +0 -1
  325. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/FormikControlled-936877004113c2a6.js +0 -1
  326. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/FormikField-6416f01524482af9.js +0 -1
  327. fides/ui-build/static/admin/_next/static/chunks/pages/poc/forms-3f4e1313d1f2969b.js +0 -1
  328. fides/ui-build/static/admin/_next/static/chunks/pages/poc/table-migration-1db7a54437db7db0.js +0 -1
  329. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-64236fd0141414fd.js +0 -1
  330. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-8cab04871908cfeb.js +0 -1
  331. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-150d40428245ee0c.js +0 -1
  332. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure-b6c876dceb16ad1b.js +0 -1
  333. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-20cdb2c8a03deae1.js +0 -1
  334. fides/ui-build/static/admin/_next/static/chunks/pages/properties/[id]-54bcc875592d1fb9.js +0 -1
  335. fides/ui-build/static/admin/_next/static/chunks/pages/properties/add-property-644dc669b508a79a.js +0 -1
  336. fides/ui-build/static/admin/_next/static/chunks/pages/properties-9a88220d03e7e02f.js +0 -1
  337. fides/ui-build/static/admin/_next/static/chunks/pages/reporting/datamap-70dc1081df37ea69.js +0 -1
  338. fides/ui-build/static/admin/_next/static/chunks/pages/settings/about/alpha-3c71b4dbcb6fd6c9.js +0 -1
  339. fides/ui-build/static/admin/_next/static/chunks/pages/settings/about-7cb16e0000dd16c9.js +0 -1
  340. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent/[configuration_id]/[purpose_id]-a18d8f12ee8dcf5d.js +0 -1
  341. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-dc220e116ad5c09e.js +0 -1
  342. fides/ui-build/static/admin/_next/static/chunks/pages/settings/custom-fields-55ddc5f25b86f28e.js +0 -1
  343. fides/ui-build/static/admin/_next/static/chunks/pages/settings/domain-records-5ca7decded228bc8.js +0 -1
  344. fides/ui-build/static/admin/_next/static/chunks/pages/settings/domains-a6fafa1be2834c40.js +0 -1
  345. fides/ui-build/static/admin/_next/static/chunks/pages/settings/email-templates-e633750d2b45ddd6.js +0 -1
  346. fides/ui-build/static/admin/_next/static/chunks/pages/settings/locations-3948686cbd372969.js +0 -1
  347. fides/ui-build/static/admin/_next/static/chunks/pages/settings/organization-04ece499c22d23f4.js +0 -1
  348. fides/ui-build/static/admin/_next/static/chunks/pages/settings/regulations-7752305084280cca.js +0 -1
  349. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/test-datasets-9e5f9066be6f218d.js +0 -1
  350. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]-86de9e6d72098e45.js +0 -1
  351. fides/ui-build/static/admin/_next/static/chunks/pages/systems-cac52e6c3abf6a15.js +0 -1
  352. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-60d5930b6855679b.js +0 -1
  353. fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/[id]-b0f4c34752d32c73.js +0 -1
  354. fides/ui-build/static/admin/_next/static/chunks/pages/user-management-7dee83dd6d9292aa.js +0 -1
  355. fides/ui-build/static/admin/_next/static/chunks/webpack-8457bad7859c44f0.js +0 -1
  356. fides/ui-build/static/admin/_next/static/css/1fdf5c593349dbc6.css +0 -1
  357. fides/ui-build/static/admin/_next/static/f_8LkSZkhtDM14f8gbC0b/_buildManifest.js +0 -1
  358. {ethyca_fides-2.63.3rc0.dist-info → ethyca_fides-2.64.1b0.dist-info}/WHEEL +0 -0
  359. {ethyca_fides-2.63.3rc0.dist-info → ethyca_fides-2.64.1b0.dist-info}/entry_points.txt +0 -0
  360. {ethyca_fides-2.63.3rc0.dist-info → ethyca_fides-2.64.1b0.dist-info}/licenses/LICENSE +0 -0
  361. {ethyca_fides-2.63.3rc0.dist-info → ethyca_fides-2.64.1b0.dist-info}/top_level.txt +0 -0
  362. /fides/ui-build/static/admin/_next/static/{f_8LkSZkhtDM14f8gbC0b → nRQ3pmK_d3F5PJE39rP2h}/_ssgManifest.js +0 -0
@@ -1,6 +1,7 @@
1
1
  import time
2
+ from copy import deepcopy
2
3
  from datetime import datetime, timedelta
3
- from typing import Any, Dict, List, Optional, Set, Tuple
4
+ from typing import Any, Optional, Tuple
4
5
 
5
6
  import requests
6
7
  from loguru import logger
@@ -21,6 +22,7 @@ from fides.api.common_exceptions import (
21
22
  from fides.api.db.session import get_db_session
22
23
  from fides.api.graph.config import CollectionAddress
23
24
  from fides.api.graph.graph import DatasetGraph
25
+ from fides.api.models.attachment import Attachment, AttachmentReferenceType
24
26
  from fides.api.models.audit_log import AuditLog, AuditLogAction
25
27
  from fides.api.models.connectionconfig import AccessLevel, ConnectionConfig
26
28
  from fides.api.models.datasetconfig import DatasetConfig
@@ -29,6 +31,7 @@ from fides.api.models.policy import (
29
31
  Policy,
30
32
  PolicyPostWebhook,
31
33
  PolicyPreWebhook,
34
+ Rule,
32
35
  WebhookTypes,
33
36
  )
34
37
  from fides.api.models.privacy_request import (
@@ -56,6 +59,10 @@ from fides.api.service.messaging.message_dispatch_service import (
56
59
  dispatch_message,
57
60
  message_send_enabled,
58
61
  )
62
+ from fides.api.service.privacy_request.attachment_handling import (
63
+ get_attachments_content,
64
+ process_attachments_for_upload,
65
+ )
59
66
  from fides.api.service.storage.storage_uploader_service import upload
60
67
  from fides.api.task.filter_results import filter_data_categories
61
68
  from fides.api.task.graph_runners import access_runner, consent_runner, erasure_runner
@@ -80,7 +87,8 @@ from fides.config.config_proxy import ConfigProxy
80
87
  class ManualWebhookResults(FidesSchema):
81
88
  """Represents manual webhook data retrieved from the cache and whether privacy request execution should continue"""
82
89
 
83
- manual_data: Dict[str, List[Dict[str, Optional[Any]]]]
90
+ manual_data_for_upload: dict[str, list[dict[str, Optional[Any]]]]
91
+ manual_data_for_storage: dict[str, list[dict[str, Optional[Any]]]]
84
92
  proceed: bool
85
93
 
86
94
 
@@ -92,17 +100,52 @@ def get_manual_webhook_access_inputs(
92
100
 
93
101
  This data will be uploaded to the user as-is, without filtering.
94
102
  """
95
- manual_inputs: Dict[str, List[Dict[str, Optional[Any]]]] = {}
103
+ manual_inputs_for_upload: dict[str, list[dict[str, Optional[Any]]]] = {}
104
+ manual_inputs_for_storage: dict[str, list[dict[str, Optional[Any]]]] = {}
96
105
 
97
106
  if not policy.get_rules_for_action(action_type=ActionType.access):
98
107
  # Don't fetch manual inputs unless this policy has an access rule
99
- return ManualWebhookResults(manual_data=manual_inputs, proceed=True)
108
+ return ManualWebhookResults(
109
+ manual_data_for_upload=manual_inputs_for_upload,
110
+ manual_data_for_storage=manual_inputs_for_storage,
111
+ proceed=True,
112
+ )
100
113
 
101
114
  try:
102
115
  for manual_webhook in AccessManualWebhook.get_enabled(db, ActionType.access):
103
- manual_inputs[manual_webhook.connection_config.key] = [
116
+ # Get the manual webhook input data
117
+ webhook_data_for_storage = (
104
118
  privacy_request.get_manual_webhook_access_input_strict(manual_webhook)
119
+ )
120
+ # Add the system name to the webhook data for display purposes
121
+ webhook_data_for_storage["system_name"] = (
122
+ manual_webhook.connection_config.system.name
123
+ )
124
+ webhook_data_for_upload = deepcopy(webhook_data_for_storage)
125
+
126
+ # Get any attachments for this webhook, load from db to ensure they have their configs
127
+ webhook_attachments = privacy_request.get_access_manual_webhook_attachments(
128
+ db, manual_webhook.id
129
+ )
130
+ if webhook_attachments:
131
+ attachment_ids = [wa.id for wa in webhook_attachments]
132
+ loaded_attachments = (
133
+ db.query(Attachment).filter(Attachment.id.in_(attachment_ids)).all()
134
+ )
135
+ (
136
+ webhook_data_for_upload["attachments"],
137
+ webhook_data_for_storage["attachments"],
138
+ ) = process_attachments_for_upload(
139
+ get_attachments_content(loaded_attachments)
140
+ )
141
+
142
+ manual_inputs_for_upload[manual_webhook.connection_config.key] = [
143
+ webhook_data_for_upload
144
+ ]
145
+ manual_inputs_for_storage[manual_webhook.connection_config.key] = [ # type: ignore[assignment]
146
+ webhook_data_for_storage
105
147
  ]
148
+
106
149
  except (
107
150
  NoCachedManualWebhookEntry,
108
151
  ValidationError,
@@ -111,19 +154,31 @@ def get_manual_webhook_access_inputs(
111
154
  logger.info(exc)
112
155
  privacy_request.status = PrivacyRequestStatus.requires_input
113
156
  privacy_request.save(db)
114
- return ManualWebhookResults(manual_data=manual_inputs, proceed=False)
157
+ return ManualWebhookResults(
158
+ manual_data_for_upload=manual_inputs_for_upload,
159
+ manual_data_for_storage=manual_inputs_for_storage,
160
+ proceed=False,
161
+ )
115
162
 
116
- return ManualWebhookResults(manual_data=manual_inputs, proceed=True)
163
+ return ManualWebhookResults(
164
+ manual_data_for_upload=manual_inputs_for_upload,
165
+ manual_data_for_storage=manual_inputs_for_storage,
166
+ proceed=True,
167
+ )
117
168
 
118
169
 
119
170
  def get_manual_webhook_erasure_inputs(
120
171
  db: Session, privacy_request: PrivacyRequest, policy: Policy
121
172
  ) -> ManualWebhookResults:
122
- manual_inputs: Dict[str, List[Dict[str, Optional[Any]]]] = {}
173
+ manual_inputs: dict[str, list[dict[str, Optional[Any]]]] = {}
123
174
 
124
175
  if not policy.get_rules_for_action(action_type=ActionType.erasure):
125
176
  # Don't fetch manual inputs unless this policy has an access rule
126
- return ManualWebhookResults(manual_data=manual_inputs, proceed=True)
177
+ return ManualWebhookResults(
178
+ manual_data_for_upload=manual_inputs,
179
+ manual_data_for_storage=manual_inputs,
180
+ proceed=True,
181
+ )
127
182
  try:
128
183
  for manual_webhook in AccessManualWebhook().get_enabled(db, ActionType.erasure):
129
184
  manual_inputs[manual_webhook.connection_config.key] = [
@@ -137,69 +192,93 @@ def get_manual_webhook_erasure_inputs(
137
192
  logger.info(exc)
138
193
  privacy_request.status = PrivacyRequestStatus.requires_input
139
194
  privacy_request.save(db)
140
- return ManualWebhookResults(manual_data=manual_inputs, proceed=False)
195
+ return ManualWebhookResults(
196
+ manual_data_for_upload=manual_inputs,
197
+ manual_data_for_storage=manual_inputs,
198
+ proceed=False,
199
+ )
141
200
 
142
- return ManualWebhookResults(manual_data=manual_inputs, proceed=True)
201
+ return ManualWebhookResults(
202
+ manual_data_for_upload=manual_inputs,
203
+ manual_data_for_storage=manual_inputs,
204
+ proceed=True,
205
+ )
143
206
 
144
207
 
145
- def run_webhooks_and_report_status(
146
- db: Session,
208
+ @log_context(capture_args={"privacy_request_id": LoggerContextKeys.privacy_request_id})
209
+ def upload_access_results(
210
+ session: Session,
211
+ policy: Policy,
212
+ rule: Rule,
213
+ results_to_upload: dict[str, list[dict[str, Optional[Any]]]],
214
+ dataset_graph: DatasetGraph,
147
215
  privacy_request: PrivacyRequest,
148
- webhook_cls: WebhookTypes,
149
- after_webhook_id: Optional[str] = None,
150
- ) -> bool:
151
- """
152
- Runs a series of webhooks either pre- or post- privacy request execution, if any are configured.
153
- Updates privacy request status if execution is paused/errored.
154
- Returns True if execution should proceed.
155
- """
156
- webhooks = db.query(webhook_cls).filter_by(policy_id=privacy_request.policy.id) # type: ignore
216
+ upload_attachments: list[dict[str, Any]],
217
+ ) -> list[str]:
218
+ """Upload results for a single rule and return download URLs and modified results."""
219
+ start_time = time.time()
220
+ download_urls: list[str] = []
221
+ storage_destination = rule.get_storage_destination(session)
157
222
 
158
- if after_webhook_id:
159
- # Only run webhooks configured to run after this Pre-Execution webhook
160
- pre_webhook = PolicyPreWebhook.get(db=db, object_id=after_webhook_id)
161
- webhooks = webhooks.filter( # type: ignore[call-arg]
162
- webhook_cls.order > pre_webhook.order, # type: ignore[union-attr]
223
+ if upload_attachments:
224
+ results_to_upload["attachments"] = upload_attachments
225
+
226
+ logger.info("Starting access request upload for rule {}", rule.key)
227
+ try:
228
+ download_url: Optional[str] = upload(
229
+ db=session,
230
+ privacy_request=privacy_request,
231
+ data=results_to_upload,
232
+ storage_key=storage_destination.key, # type: ignore
233
+ data_category_field_mapping=dataset_graph.data_category_field_mapping,
234
+ data_use_map=privacy_request.get_cached_data_use_map(),
235
+ )
236
+ if download_url:
237
+ download_urls.append(download_url)
238
+ logger.bind(
239
+ time_taken=time.time() - start_time,
240
+ ).info("Access package upload successful for privacy request.")
241
+ privacy_request.add_success_execution_log(
242
+ session,
243
+ connection_key=None,
244
+ dataset_name="Access package upload",
245
+ collection_name=None,
246
+ message="Access package upload successful for privacy request.",
247
+ action_type=ActionType.access,
248
+ )
249
+ except common_exceptions.StorageUploadError as exc:
250
+ logger.error(
251
+ "Error uploading subject access data for rule {} on policy {}: {}",
252
+ rule.key,
253
+ policy.key,
254
+ Pii(str(exc)),
255
+ )
256
+ privacy_request.add_error_execution_log(
257
+ session,
258
+ connection_key=None,
259
+ dataset_name="Access package upload",
260
+ collection_name=None,
261
+ message="Access package upload failed for privacy request.",
262
+ action_type=ActionType.access,
163
263
  )
264
+ privacy_request.status = PrivacyRequestStatus.error
164
265
 
165
- current_step = CurrentStep[f"{webhook_cls.prefix}_webhooks"]
266
+ return download_urls
166
267
 
167
- for webhook in webhooks.order_by(webhook_cls.order): # type: ignore[union-attr]
168
- try:
169
- privacy_request.trigger_policy_webhook(
170
- webhook=webhook,
171
- policy_action=privacy_request.policy.get_action_type(),
172
- )
173
- except PrivacyRequestPaused:
174
- logger.info(
175
- "Pausing execution of privacy request {}. Halt instruction received from webhook {}.",
176
- privacy_request.id,
177
- webhook.key,
178
- )
179
- privacy_request.pause_processing(db)
180
- initiate_paused_privacy_request_followup(privacy_request)
181
- return False
182
- except ClientUnsuccessfulException as exc:
183
- logger.error(
184
- "Privacy Request '{}' exited after response from webhook '{}': {}.",
185
- privacy_request.id,
186
- webhook.key,
187
- Pii(str(exc.args[0])),
188
- )
189
- privacy_request.error_processing(db)
190
- privacy_request.cache_failed_checkpoint_details(current_step)
191
- return False
192
- except PydanticValidationError:
193
- logger.error(
194
- "Privacy Request '{}' errored due to response validation error from webhook '{}'.",
195
- privacy_request.id,
196
- webhook.key,
197
- )
198
- privacy_request.error_processing(db)
199
- privacy_request.cache_failed_checkpoint_details(current_step)
200
- return False
201
268
 
202
- return True
269
+ def save_access_results(
270
+ session: Session,
271
+ privacy_request: PrivacyRequest,
272
+ download_urls: list[str],
273
+ rule_filtered_results: dict[str, dict[str, list[dict[str, Optional[Any]]]]],
274
+ ) -> None:
275
+ """Save the results we uploaded to the user for later retrieval"""
276
+ # Save the results we uploaded to the user for later retrieval
277
+ privacy_request.save_filtered_access_results(session, rule_filtered_results)
278
+ # Saving access request URL's on the privacy request in case DSR 3.0
279
+ # exits processing before the email is sent
280
+ privacy_request.access_result_urls = {"access_result_urls": download_urls}
281
+ privacy_request.save(session)
203
282
 
204
283
 
205
284
  @log_context(
@@ -207,29 +286,40 @@ def run_webhooks_and_report_status(
207
286
  "privacy_request_id": LoggerContextKeys.privacy_request_id,
208
287
  }
209
288
  )
210
- def upload_access_results( # pylint: disable=R0912
289
+ def upload_and_save_access_results( # pylint: disable=R0912
211
290
  session: Session,
212
291
  policy: Policy,
213
- access_result: Dict[str, List[Row]],
292
+ access_result: dict[str, list[Row]],
214
293
  dataset_graph: DatasetGraph,
215
294
  privacy_request: PrivacyRequest,
216
- manual_data: Dict[str, List[Dict[str, Optional[Any]]]],
217
- fides_connector_datasets: Set[str],
218
- ) -> List[str]:
295
+ manual_data_access_results: ManualWebhookResults,
296
+ fides_connector_datasets: set[str],
297
+ ) -> list[str]:
219
298
  """Process the data uploads after the access portion of the privacy request has completed"""
220
- start_time = time.time()
221
- download_urls: List[str] = []
299
+ download_urls: list[str] = []
300
+ # Remove manual webhook attachments from the list of attachments
301
+ # This is done because the manual webhook attachments are already included in the manual_data
302
+ loaded_attachments = [
303
+ attachment
304
+ for attachment in privacy_request.attachments
305
+ if AttachmentReferenceType.access_manual_webhook
306
+ not in [ref.reference_type for ref in attachment.references]
307
+ ]
308
+ attachments = get_attachments_content(loaded_attachments)
309
+ # Process attachments once for both upload and storage
310
+ upload_attachments, storage_attachments = process_attachments_for_upload(
311
+ attachments
312
+ )
313
+
222
314
  if not access_result:
223
315
  logger.info("No results returned for access request")
224
316
 
225
- rule_filtered_results: Dict[str, Dict[str, List[Row]]] = {}
317
+ rule_filtered_results: dict[str, dict[str, list[dict[str, Optional[Any]]]]] = {}
226
318
  for rule in policy.get_rules_for_action( # pylint: disable=R1702
227
319
  action_type=ActionType.access
228
320
  ):
229
- storage_destination = rule.get_storage_destination(session)
230
-
231
- target_categories: Set[str] = {target.data_category for target in rule.targets} # type: ignore[attr-defined]
232
- filtered_results: Dict[str, List[Dict[str, Optional[Any]]]] = (
321
+ target_categories: set[str] = {target.data_category for target in rule.targets} # type: ignore[attr-defined]
322
+ filtered_results: dict[str, list[dict[str, Optional[Any]]]] = (
233
323
  filter_data_categories(
234
324
  access_result,
235
325
  target_categories,
@@ -238,59 +328,28 @@ def upload_access_results( # pylint: disable=R0912
238
328
  fides_connector_datasets,
239
329
  )
240
330
  )
331
+ # Create a copy of filtered results to modify for upload
332
+ results_to_upload = deepcopy(filtered_results)
333
+ results_to_upload.update(manual_data_access_results.manual_data_for_upload)
334
+
335
+ rule_download_urls = upload_access_results(
336
+ session,
337
+ policy,
338
+ rule,
339
+ results_to_upload,
340
+ dataset_graph,
341
+ privacy_request,
342
+ upload_attachments,
343
+ )
344
+ download_urls.extend(rule_download_urls)
241
345
 
242
- filtered_results.update(
243
- manual_data
244
- ) # Add manual data directly to each upload packet
346
+ # Create results for storage
347
+ filtered_results.update(manual_data_access_results.manual_data_for_storage)
348
+ if storage_attachments:
349
+ filtered_results["attachments"] = storage_attachments
245
350
  rule_filtered_results[rule.key] = filtered_results
246
351
 
247
- logger.info(
248
- "Starting access request upload for rule {}",
249
- rule.key,
250
- )
251
- try:
252
- download_url: Optional[str] = upload(
253
- db=session,
254
- privacy_request=privacy_request,
255
- data=filtered_results,
256
- storage_key=storage_destination.key, # type: ignore
257
- data_category_field_mapping=dataset_graph.data_category_field_mapping,
258
- data_use_map=privacy_request.get_cached_data_use_map(),
259
- )
260
- if download_url:
261
- download_urls.append(download_url)
262
- privacy_request.add_success_execution_log(
263
- session,
264
- connection_key=None,
265
- dataset_name="Access package upload",
266
- collection_name=None,
267
- message="Access package upload successful for privacy request.",
268
- action_type=ActionType.access,
269
- )
270
- logger.bind(
271
- time_taken=time.time() - start_time,
272
- ).info("Access package upload successful for privacy request.")
273
- except common_exceptions.StorageUploadError as exc:
274
- logger.bind(
275
- policy_key=policy.key,
276
- rule_key=rule.key,
277
- error=Pii(str(exc)),
278
- ).error("Error uploading subject access data for rule.")
279
- privacy_request.add_error_execution_log(
280
- session,
281
- connection_key=None,
282
- dataset_name="Access package upload",
283
- collection_name=None,
284
- message="Access package upload failed for privacy request.",
285
- action_type=ActionType.access,
286
- )
287
- privacy_request.status = PrivacyRequestStatus.error
288
- # Save the results we uploaded to the user for later retrieval
289
- privacy_request.save_filtered_access_results(session, rule_filtered_results)
290
- # Saving access request URL's on the privacy request in case DSR 3.0
291
- # exits processing before the email is sent
292
- privacy_request.access_result_urls = {"access_result_urls": download_urls}
293
- privacy_request.save(session)
352
+ save_access_results(session, privacy_request, download_urls, rule_filtered_results)
294
353
  return download_urls
295
354
 
296
355
 
@@ -408,7 +467,7 @@ def run_privacy_request(
408
467
  for key, value in privacy_request.get_cached_identity_data().items()
409
468
  }
410
469
  connection_configs = ConnectionConfig.all(db=session)
411
- fides_connector_datasets: Set[str] = filter_fides_connector_datasets(
470
+ fides_connector_datasets: set[str] = filter_fides_connector_datasets(
412
471
  connection_configs
413
472
  )
414
473
 
@@ -431,8 +490,8 @@ def run_privacy_request(
431
490
  )
432
491
 
433
492
  # Upload Access Results CHECKPOINT
434
- access_result_urls: List[str] = []
435
- raw_access_results: Dict = privacy_request.get_raw_access_results()
493
+ access_result_urls: list[str] = []
494
+ raw_access_results: dict = privacy_request.get_raw_access_results()
436
495
  if (
437
496
  policy.get_rules_for_action(action_type=ActionType.access)
438
497
  or policy.get_rules_for_action(
@@ -448,13 +507,13 @@ def run_privacy_request(
448
507
  filtered_access_results = filter_by_enabled_actions(
449
508
  raw_access_results, connection_configs
450
509
  )
451
- access_result_urls = upload_access_results(
510
+ access_result_urls = upload_and_save_access_results(
452
511
  session,
453
512
  policy,
454
513
  filtered_access_results,
455
514
  dataset_graph,
456
515
  privacy_request,
457
- manual_webhook_access_results.manual_data,
516
+ manual_webhook_access_results,
458
517
  fides_connector_datasets,
459
518
  )
460
519
 
@@ -643,8 +702,8 @@ def run_privacy_request(
643
702
  def initiate_privacy_request_completion_email(
644
703
  session: Session,
645
704
  policy: Policy,
646
- access_result_urls: List[str],
647
- identity_data: Dict[str, Any],
705
+ access_result_urls: list[str],
706
+ identity_data: dict[str, Any],
648
707
  property_id: Optional[str],
649
708
  ) -> None:
650
709
  """
@@ -727,8 +786,8 @@ def mark_paused_privacy_request_as_expired(privacy_request_id: str) -> None:
727
786
  def _retrieve_child_results( # pylint: disable=R0911
728
787
  fides_connector: Tuple[str, ConnectionConfig],
729
788
  rule_key: str,
730
- access_result: Dict[str, List[Row]],
731
- ) -> Optional[List[Dict[str, Optional[List[Row]]]]]:
789
+ access_result: dict[str, list[Row]],
790
+ ) -> Optional[list[dict[str, Optional[list[Row]]]]]:
732
791
  """Get child access request results to add to upload."""
733
792
  try:
734
793
  connector = FidesConnector(fides_connector[1])
@@ -815,7 +874,7 @@ def get_erasure_email_connection_configs(db: Session) -> Query:
815
874
 
816
875
 
817
876
  def needs_batch_email_send(
818
- db: Session, user_identities: Dict[str, Any], privacy_request: PrivacyRequest
877
+ db: Session, user_identities: dict[str, Any], privacy_request: PrivacyRequest
819
878
  ) -> bool:
820
879
  """
821
880
  Delegates the "needs email" check to each configured email or
@@ -825,8 +884,8 @@ def needs_batch_email_send(
825
884
  If we don't need to send any emails, add skipped logs for any
826
885
  relevant erasure and consent email connectors.
827
886
  """
828
- can_skip_erasure_email: List[ConnectionConfig] = []
829
- can_skip_consent_email: List[ConnectionConfig] = []
887
+ can_skip_erasure_email: list[ConnectionConfig] = []
888
+ can_skip_consent_email: list[ConnectionConfig] = []
830
889
 
831
890
  needs_email_send: bool = False
832
891
 
@@ -857,8 +916,8 @@ def needs_batch_email_send(
857
916
  def _create_execution_logs_for_skipped_email_send(
858
917
  db: Session,
859
918
  privacy_request: PrivacyRequest,
860
- can_skip_erasure_email: List[ConnectionConfig],
861
- can_skip_consent_email: List[ConnectionConfig],
919
+ can_skip_erasure_email: list[ConnectionConfig],
920
+ can_skip_consent_email: list[ConnectionConfig],
862
921
  ) -> None:
863
922
  """Create skipped execution logs for relevant connectors
864
923
  if this privacy request does not need an email send at all. For consent requests,
@@ -874,3 +933,63 @@ def _create_execution_logs_for_skipped_email_send(
874
933
  for connection_config in can_skip_consent_email:
875
934
  connector = get_connector(connection_config)
876
935
  connector.add_skipped_log(db, privacy_request) # type: ignore[attr-defined]
936
+
937
+
938
+ def run_webhooks_and_report_status(
939
+ db: Session,
940
+ privacy_request: PrivacyRequest,
941
+ webhook_cls: WebhookTypes,
942
+ after_webhook_id: Optional[str] = None,
943
+ ) -> bool:
944
+ """
945
+ Runs a series of webhooks either pre- or post- privacy request execution, if any are configured.
946
+ Updates privacy request status if execution is paused/errored.
947
+ Returns True if execution should proceed.
948
+ """
949
+ webhooks = db.query(webhook_cls).filter_by(policy_id=privacy_request.policy.id) # type: ignore
950
+
951
+ if after_webhook_id:
952
+ # Only run webhooks configured to run after this Pre-Execution webhook
953
+ pre_webhook = PolicyPreWebhook.get(db=db, object_id=after_webhook_id)
954
+ webhooks = webhooks.filter( # type: ignore[call-arg]
955
+ webhook_cls.order > pre_webhook.order, # type: ignore[union-attr]
956
+ )
957
+
958
+ current_step = CurrentStep[f"{webhook_cls.prefix}_webhooks"]
959
+
960
+ for webhook in webhooks.order_by(webhook_cls.order): # type: ignore[union-attr]
961
+ try:
962
+ privacy_request.trigger_policy_webhook(
963
+ webhook=webhook,
964
+ policy_action=privacy_request.policy.get_action_type(),
965
+ )
966
+ except PrivacyRequestPaused:
967
+ logger.info(
968
+ "Pausing execution of privacy request {}. Halt instruction received from webhook {}.",
969
+ privacy_request.id,
970
+ webhook.key,
971
+ )
972
+ privacy_request.pause_processing(db)
973
+ initiate_paused_privacy_request_followup(privacy_request)
974
+ return False
975
+ except ClientUnsuccessfulException as exc:
976
+ logger.error(
977
+ "Privacy Request '{}' exited after response from webhook '{}': {}.",
978
+ privacy_request.id,
979
+ webhook.key,
980
+ Pii(str(exc.args[0])),
981
+ )
982
+ privacy_request.error_processing(db)
983
+ privacy_request.cache_failed_checkpoint_details(current_step)
984
+ return False
985
+ except PydanticValidationError:
986
+ logger.error(
987
+ "Privacy Request '{}' errored due to response validation error from webhook '{}'.",
988
+ privacy_request.id,
989
+ webhook.key,
990
+ )
991
+ privacy_request.error_processing(db)
992
+ privacy_request.cache_failed_checkpoint_details(current_step)
993
+ return False
994
+
995
+ return True
@@ -1,6 +1,6 @@
1
- from typing import Dict, Optional
1
+ from typing import Optional
2
2
 
3
- from google.cloud.storage import Client # type: ignore
3
+ from google.cloud.storage import Blob, Client # type: ignore
4
4
  from google.oauth2 import service_account
5
5
  from loguru import logger
6
6
 
@@ -10,7 +10,7 @@ from fides.api.schemas.storage.storage import GCSAuthMethod
10
10
 
11
11
  def get_gcs_client(
12
12
  auth_method: str,
13
- storage_secrets: Optional[Dict],
13
+ storage_secrets: Optional[dict],
14
14
  ) -> Client:
15
15
  """
16
16
  Abstraction to retrieve a GCS client using secrets.
@@ -36,3 +36,15 @@ def get_gcs_client(
36
36
  )
37
37
 
38
38
  return storage_client
39
+
40
+
41
+ def get_gcs_blob(
42
+ auth_method: str, storage_secrets: Optional[dict], bucket_name: str, file_key: str
43
+ ) -> Blob:
44
+ try:
45
+ storage_client = get_gcs_client(auth_method, storage_secrets)
46
+ bucket = storage_client.bucket(bucket_name)
47
+ return bucket.blob(file_key)
48
+ except Exception as e:
49
+ logger.error(f"Error getting GCS blob: {str(e)}")
50
+ raise e