ethyca-fides 2.66.2rc0__py2.py3-none-any.whl → 2.67.0__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ethyca-fides might be problematic. Click here for more details.

Files changed (335) hide show
  1. {ethyca_fides-2.66.2rc0.dist-info → ethyca_fides-2.67.0.dist-info}/METADATA +1 -1
  2. {ethyca_fides-2.66.2rc0.dist-info → ethyca_fides-2.67.0.dist-info}/RECORD +297 -282
  3. fides/_version.py +3 -3
  4. fides/api/alembic/migrations/versions/7e9a2b52f498_adding_masking_secrets.py +60 -0
  5. fides/api/alembic/migrations/versions/a7065df4dcf1_add_finalized_fields_to_privacy_request.py +65 -0
  6. fides/api/alembic/migrations/versions/d0031087eacb_create_manualtaskconditionaldependency_.py +106 -0
  7. fides/api/api/v1/endpoints/dataset_config_endpoints.py +13 -5
  8. fides/api/api/v1/endpoints/drp_endpoints.py +7 -1
  9. fides/api/api/v1/endpoints/privacy_request_endpoints.py +44 -1
  10. fides/api/api/v1/endpoints/user_endpoints.py +83 -7
  11. fides/api/app_setup.py +3 -2
  12. fides/api/common_exceptions.py +8 -0
  13. fides/api/db/base.py +1 -0
  14. fides/api/db/database.py +1 -1
  15. fides/api/graph/execution.py +46 -0
  16. fides/api/graph/graph.py +13 -2
  17. fides/api/graph/traversal.py +126 -39
  18. fides/api/models/manual_task/__init__.py +2 -0
  19. fides/api/models/manual_task/conditional_dependency.py +144 -0
  20. fides/api/models/{manual_task.py → manual_task/manual_task.py} +10 -0
  21. fides/api/models/masking_secret.py +72 -0
  22. fides/api/models/policy.py +23 -0
  23. fides/api/models/privacy_request/execution_log.py +1 -0
  24. fides/api/models/privacy_request/privacy_request.py +64 -26
  25. fides/api/oauth/roles.py +2 -0
  26. fides/api/schemas/application_config.py +12 -1
  27. fides/api/schemas/connection_configuration/connection_secrets_datahub.py +10 -1
  28. fides/api/schemas/masking/masking_secrets.py +1 -1
  29. fides/api/schemas/policy.py +1 -0
  30. fides/api/schemas/privacy_request.py +5 -0
  31. fides/api/service/connectors/base_connector.py +15 -0
  32. fides/api/service/connectors/bigquery_connector.py +72 -19
  33. fides/api/service/connectors/dynamodb_connector.py +2 -1
  34. fides/api/service/connectors/fides_connector.py +1 -0
  35. fides/api/service/connectors/http_connector.py +1 -0
  36. fides/api/service/connectors/manual_task_connector.py +1 -0
  37. fides/api/service/connectors/manual_webhook_connector.py +2 -1
  38. fides/api/service/connectors/mongodb_connector.py +1 -0
  39. fides/api/service/connectors/okta_connector.py +1 -0
  40. fides/api/service/connectors/query_configs/bigquery_query_config.py +95 -36
  41. fides/api/service/connectors/query_configs/snowflake_query_config.py +3 -3
  42. fides/api/service/connectors/rds_mysql_connector.py +1 -0
  43. fides/api/service/connectors/rds_postgres_connector.py +1 -0
  44. fides/api/service/connectors/s3_connector.py +1 -0
  45. fides/api/service/connectors/saas_connector.py +1 -0
  46. fides/api/service/connectors/scylla_connector.py +1 -0
  47. fides/api/service/connectors/snowflake_connector.py +55 -2
  48. fides/api/service/connectors/sql_connector.py +159 -13
  49. fides/api/service/connectors/website_connector.py +1 -0
  50. fides/api/service/privacy_request/dsr_package/templates/welcome.html +2 -2
  51. fides/api/service/privacy_request/request_runner_service.py +145 -55
  52. fides/api/service/privacy_request/request_service.py +172 -52
  53. fides/api/task/conditional_dependencies/__init__.py +0 -0
  54. fides/api/task/conditional_dependencies/evaluator.py +109 -0
  55. fides/api/task/conditional_dependencies/schemas.py +54 -0
  56. fides/api/task/create_request_tasks.py +1 -1
  57. fides/api/task/deprecated_graph_task.py +24 -6
  58. fides/api/task/execute_request_tasks.py +93 -12
  59. fides/api/task/filter_results.py +1 -1
  60. fides/api/task/graph_task.py +86 -5
  61. fides/api/task/manual/manual_task_address.py +46 -0
  62. fides/api/task/manual/manual_task_graph_task.py +118 -126
  63. fides/api/task/manual/manual_task_utils.py +52 -105
  64. fides/api/util/aws_util.py +5 -1
  65. fides/api/util/cache.py +61 -0
  66. fides/api/util/encryption/secrets_util.py +48 -18
  67. fides/api/util/memory_watchdog.py +286 -0
  68. fides/common/api/scope_registry.py +3 -0
  69. fides/common/api/v1/urn_registry.py +1 -1
  70. fides/config/execution_settings.py +12 -0
  71. fides/config/utils.py +2 -0
  72. fides/service/privacy_request/privacy_request_service.py +6 -1
  73. fides/ui-build/static/admin/404.html +1 -1
  74. fides/ui-build/static/admin/_next/static/MNlh9olWjgbqAHKyQY3LF/_buildManifest.js +1 -0
  75. fides/ui-build/static/admin/_next/static/chunks/1316-2606e19807c08aa5.js +1 -0
  76. fides/ui-build/static/admin/_next/static/chunks/1467-8808ec8836e033f9.js +1 -0
  77. fides/ui-build/static/admin/_next/static/chunks/1817-b78b58ae3b75d75a.js +1 -0
  78. fides/ui-build/static/admin/_next/static/chunks/1975.7d4634a0e823a02b.js +1 -0
  79. fides/ui-build/static/admin/_next/static/chunks/{203-5a663f465ba26bb4.js → 203-cd78ea279cecba60.js} +1 -1
  80. fides/ui-build/static/admin/_next/static/chunks/2150-930ffaf2c4718edc.js +1 -0
  81. fides/ui-build/static/admin/_next/static/chunks/255-1bc0cbef7a59cdc6.js +1 -0
  82. fides/ui-build/static/admin/_next/static/chunks/{3450-0ba194991d0cca88.js → 3450-69f4e16978971bb8.js} +1 -1
  83. fides/ui-build/static/admin/_next/static/chunks/346-aa3b88efb85f2e28.js +1 -0
  84. fides/ui-build/static/admin/_next/static/chunks/3550-d04125c828d591a1.js +1 -0
  85. fides/ui-build/static/admin/_next/static/chunks/{3855-e172870d3e21b0dd.js → 3855-509ca7ac99b5eada.js} +1 -1
  86. fides/ui-build/static/admin/_next/static/chunks/{3872-46cebf7ec1b31a2b.js → 3872-0a0f0032ca39a93f.js} +1 -1
  87. fides/ui-build/static/admin/_next/static/chunks/409-ea70638a59296659.js +1 -0
  88. fides/ui-build/static/admin/_next/static/chunks/{4121-2bc09fc4ddbfe5cb.js → 4121-877e19d3fa078c7b.js} +1 -1
  89. fides/ui-build/static/admin/_next/static/chunks/{4230-60100f7ef3ddcde1.js → 4230-114e31621c19ea69.js} +1 -1
  90. fides/ui-build/static/admin/_next/static/chunks/4259.d1507e0db19cbed7.js +1 -0
  91. fides/ui-build/static/admin/_next/static/chunks/431-1db919f6569a4021.js +1 -0
  92. fides/ui-build/static/admin/_next/static/chunks/{4608-bbb7bf511a05c3c2.js → 4608-f16f281f2d05d963.js} +1 -1
  93. fides/ui-build/static/admin/_next/static/chunks/5163-e682273cd76a7d07.js +1 -0
  94. fides/ui-build/static/admin/_next/static/chunks/5309-d9a488457898263b.js +1 -0
  95. fides/ui-build/static/admin/_next/static/chunks/{905-ffdbd0b14167e8bd.js → 5596-4378b2927dae65b2.js} +3 -3
  96. fides/ui-build/static/admin/_next/static/chunks/5619-9b50cec521203989.js +1 -0
  97. fides/ui-build/static/admin/_next/static/chunks/{6084-7178ff6ea6822475.js → 6084-ddbad3149364725d.js} +1 -1
  98. fides/ui-build/static/admin/_next/static/chunks/6148-59a59d5c5925344f.js +1 -0
  99. fides/ui-build/static/admin/_next/static/chunks/6419-d0c00d661b01f8fa.js +1 -0
  100. fides/ui-build/static/admin/_next/static/chunks/{6662-507be5d46e5b719b.js → 6662-a9e54ead3dc53644.js} +1 -1
  101. fides/ui-build/static/admin/_next/static/chunks/6780-b42a27e72707936d.js +1 -0
  102. fides/ui-build/static/admin/_next/static/chunks/{6853-2ad3e08fe6f9f5f2.js → 6853-d0190d2cca9dbde2.js} +1 -1
  103. fides/ui-build/static/admin/_next/static/chunks/{6882-6af16fef26c21e06.js → 6882-59ea739e3616ce83.js} +1 -1
  104. fides/ui-build/static/admin/_next/static/chunks/6954-ba98e778a5b45ebf.js +1 -0
  105. fides/ui-build/static/admin/_next/static/chunks/{7476-281ee9a8286556f3.js → 7476-cc0d9a94ed7aad53.js} +1 -1
  106. fides/ui-build/static/admin/_next/static/chunks/7725-539d3a906f627531.js +1 -0
  107. fides/ui-build/static/admin/_next/static/chunks/{787-fb41002f797eb2df.js → 787-c57185ad89c4e288.js} +1 -1
  108. fides/ui-build/static/admin/_next/static/chunks/{79-7e87aff851423d4a.js → 79-2aab56be75e16187.js} +1 -1
  109. fides/ui-build/static/admin/_next/static/chunks/{796-329a5f823ec258a5.js → 796-3bdda2a7868464af.js} +1 -1
  110. fides/ui-build/static/admin/_next/static/chunks/8735-40caf91800a3610c.js +1 -0
  111. fides/ui-build/static/admin/_next/static/chunks/8765-f622a35b40a7ec63.js +1 -0
  112. fides/ui-build/static/admin/_next/static/chunks/9046-7085a401297c5520.js +1 -0
  113. fides/ui-build/static/admin/_next/static/chunks/9187-7438242f0d380bb0.js +1 -0
  114. fides/ui-build/static/admin/_next/static/chunks/{9226-746771d47dff6266.js → 9226-2dcac54ab3fb94be.js} +1 -1
  115. fides/ui-build/static/admin/_next/static/chunks/9278-08cc704317fe535e.js +1 -0
  116. fides/ui-build/static/admin/_next/static/chunks/{9951-9b753ad7c3f51bdf.js → 9951-7c6639e5d062779e.js} +1 -1
  117. fides/ui-build/static/admin/_next/static/chunks/pages/{_app-39ccb07327c2c5d5.js → _app-750d6bd16c971bb9.js} +56 -56
  118. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{manual-98777246bec9dc2a.js → manual-2a655ff3a97f2492.js} +1 -1
  119. fides/ui-build/static/admin/_next/static/chunks/pages/{add-systems-a71c0aff4e0e6535.js → add-systems-0902f0bb4080643e.js} +1 -1
  120. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{[id]-1edf582ba3cd3bbb.js → [id]-f22ddd9b48a5c418.js} +1 -1
  121. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{new-06bb3b0bf097fcdb.js → new-e74cb5ea87f15b40.js} +1 -1
  122. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-experience-685771e5f7196d87.js → privacy-experience-21f997c69fc3b4c2.js} +1 -1
  123. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{[id]-6ccedc70dc447089.js → [id]-da4124b7600a2a1d.js} +1 -1
  124. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{new-944bca1cc57985b5.js → new-a57d251c88ce68ae.js} +1 -1
  125. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-notices-84f4bd14ce8673bc.js → privacy-notices-ad105181bc91209b.js} +1 -1
  126. fides/ui-build/static/admin/_next/static/chunks/pages/consent/reporting-b0c4235fe6d0b0c8.js +1 -0
  127. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]/{[resourceUrn]-11d52f1570759c4d.js → [resourceUrn]-aad6047a4604b945.js} +1 -1
  128. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{projects-32eac8bbd217615a.js → projects-29784a11fe0fbd0a.js} +1 -1
  129. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/resources/{[resourceUrn]-b83afa5565d0c84e.js → [resourceUrn]-b6b98cea25dd94fa.js} +1 -1
  130. fides/ui-build/static/admin/_next/static/chunks/pages/{data-catalog-6f630d42ac9fb6b4.js → data-catalog-7770a8dc34bd0fc0.js} +1 -1
  131. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-3e5725cd06d7fe6c.js +1 -0
  132. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]-92b0bd97d8e79340.js +1 -0
  133. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-ee3c0a103346fc06.js +1 -0
  134. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{activity-9aa744d56cdacb0d.js → activity-ad6a84a6276f914c.js} +1 -1
  135. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/discovery/{[resourceUrn]-14bd7500362ff224.js → [resourceUrn]-f98dd251babb7e28.js} +1 -1
  136. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{discovery-9e7dfd5a6acc2e8f.js → discovery-56eb4c014f0d96a3.js} +1 -1
  137. fides/ui-build/static/admin/_next/static/chunks/pages/datamap-d23b3ae139f0428b.js +1 -0
  138. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/{[...subfieldNames]-c0d2bfd465df20e0.js → [...subfieldNames]-15301bd6bf7cf718.js} +1 -1
  139. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/{[collectionName]-28280a8a39a6e37c.js → [collectionName]-0fa72873e464f581.js} +1 -1
  140. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/{new-82fb246d87e58ebd.js → new-0d50084fbdf9b84c.js} +1 -1
  141. fides/ui-build/static/admin/_next/static/chunks/pages/{dataset-20165c31ab1bc7cf.js → dataset-f3348d0a92543bab.js} +1 -1
  142. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{[id]-b4a6bcc87d126840.js → [id]-7d6027570d05c57f.js} +1 -1
  143. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{new-f95d7b0bbfc58f5a.js → new-c6614583b14dc9f2.js} +1 -1
  144. fides/ui-build/static/admin/_next/static/chunks/pages/{fides-js-docs-5d8fd1af75f19e2f.js → fides-js-docs-1f4335dca5c09860.js} +1 -1
  145. fides/ui-build/static/admin/_next/static/chunks/pages/{index-1919aab9e5834b51.js → index-fbf9b845bb901238.js} +1 -1
  146. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-8e346fb36e8034d2.js +1 -0
  147. fides/ui-build/static/admin/_next/static/chunks/pages/{integrations-e2d5d7e2a5265e68.js → integrations-7f15cd8538cdc24d.js} +1 -1
  148. fides/ui-build/static/admin/_next/static/chunks/pages/messaging-1bae386d8c190348.js +1 -0
  149. fides/ui-build/static/admin/_next/static/chunks/pages/poc/{table-migration-69ad86b7a8a9a115.js → table-migration-05616e2ae20ff4f8.js} +1 -1
  150. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-79f1576b1126975c.js +1 -0
  151. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-f1d818242d8550f8.js +1 -0
  152. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-d40a26bddb126c5c.js +1 -0
  153. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-96a08c4431b5462c.js +1 -0
  154. fides/ui-build/static/admin/_next/static/chunks/pages/reporting/datamap-9d1840f8309b706e.js +1 -0
  155. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent/[configuration_id]/{[purpose_id]-fc201657f4a782c7.js → [purpose_id]-e891d01ece59669e.js} +1 -1
  156. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{consent-c2d39cba8396ef3a.js → consent-f61b87e79367865b.js} +1 -1
  157. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{custom-fields-d992103cc55901ae.js → custom-fields-f8eea5d508c60c64.js} +1 -1
  158. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{locations-023e1895552817de.js → locations-ed6a140b362c5baa.js} +1 -1
  159. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{organization-ac403c0886b20e20.js → organization-ff9a34264d48c35f.js} +1 -1
  160. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/{test-datasets-7a3396ac819c7904.js → test-datasets-a4b6d41ca679298b.js} +1 -1
  161. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/{[id]-8314a819837f5b2a.js → [id]-c8f5fbaa83dd9945.js} +1 -1
  162. fides/ui-build/static/admin/_next/static/chunks/pages/{systems-21f423a7c417aa9d.js → systems-c05b49ddec1a1b4f.js} +1 -1
  163. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-df0d88716578e295.js +1 -0
  164. fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/[id]-da68efc31998dc66.js +1 -0
  165. fides/ui-build/static/admin/_next/static/chunks/pages/{user-management-173ac3a1ed2b05a6.js → user-management-e98dfc7d4f2a4e16.js} +1 -1
  166. fides/ui-build/static/admin/_next/static/chunks/webpack-90e8ec1fc5c6455b.js +1 -0
  167. fides/ui-build/static/admin/_next/static/css/{5bfb2473e5701527.css → 23cf870196941c9a.css} +1 -1
  168. fides/ui-build/static/admin/_next/static/css/{94965f224bc991e9.css → 8bc1833f1fa53ff0.css} +1 -1
  169. fides/ui-build/static/admin/_next/static/css/d9924caa849931b3.css +1 -0
  170. fides/ui-build/static/admin/_next/static/css/dbcf63488933a4d5.css +29 -0
  171. fides/ui-build/static/admin/add-systems/manual.html +1 -1
  172. fides/ui-build/static/admin/add-systems/multiple.html +1 -1
  173. fides/ui-build/static/admin/add-systems.html +1 -1
  174. fides/ui-build/static/admin/consent/configure/add-vendors.html +1 -1
  175. fides/ui-build/static/admin/consent/configure.html +1 -1
  176. fides/ui-build/static/admin/consent/privacy-experience/[id].html +1 -1
  177. fides/ui-build/static/admin/consent/privacy-experience/new.html +1 -1
  178. fides/ui-build/static/admin/consent/privacy-experience.html +1 -1
  179. fides/ui-build/static/admin/consent/privacy-notices/[id].html +1 -1
  180. fides/ui-build/static/admin/consent/privacy-notices/new.html +1 -1
  181. fides/ui-build/static/admin/consent/privacy-notices.html +1 -1
  182. fides/ui-build/static/admin/consent/properties.html +1 -1
  183. fides/ui-build/static/admin/consent/reporting.html +1 -1
  184. fides/ui-build/static/admin/consent.html +1 -1
  185. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn].html +1 -1
  186. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn].html +1 -1
  187. fides/ui-build/static/admin/data-catalog/[systemId]/projects.html +1 -1
  188. fides/ui-build/static/admin/data-catalog/[systemId]/resources/[resourceUrn].html +1 -1
  189. fides/ui-build/static/admin/data-catalog/[systemId]/resources.html +1 -1
  190. fides/ui-build/static/admin/data-catalog.html +1 -1
  191. fides/ui-build/static/admin/data-discovery/action-center/[monitorId]/[systemId].html +1 -1
  192. fides/ui-build/static/admin/data-discovery/action-center/[monitorId].html +1 -1
  193. fides/ui-build/static/admin/data-discovery/action-center.html +1 -1
  194. fides/ui-build/static/admin/data-discovery/activity.html +1 -1
  195. fides/ui-build/static/admin/data-discovery/detection/[resourceUrn].html +1 -1
  196. fides/ui-build/static/admin/data-discovery/detection.html +1 -1
  197. fides/ui-build/static/admin/data-discovery/discovery/[resourceUrn].html +1 -1
  198. fides/ui-build/static/admin/data-discovery/discovery.html +1 -1
  199. fides/ui-build/static/admin/datamap.html +1 -1
  200. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName]/[...subfieldNames].html +1 -1
  201. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName].html +1 -1
  202. fides/ui-build/static/admin/dataset/[datasetId].html +1 -1
  203. fides/ui-build/static/admin/dataset/new.html +1 -1
  204. fides/ui-build/static/admin/dataset.html +1 -1
  205. fides/ui-build/static/admin/datastore-connection/[id].html +1 -1
  206. fides/ui-build/static/admin/datastore-connection/new.html +1 -1
  207. fides/ui-build/static/admin/datastore-connection.html +1 -1
  208. fides/ui-build/static/admin/index.html +1 -1
  209. fides/ui-build/static/admin/integrations/[id].html +1 -1
  210. fides/ui-build/static/admin/integrations.html +1 -1
  211. fides/ui-build/static/admin/lib/fides-ext-gpp.js +1 -1
  212. fides/ui-build/static/admin/lib/fides-headless.js +1 -1
  213. fides/ui-build/static/admin/lib/fides-preview.js +1 -1
  214. fides/ui-build/static/admin/lib/fides-tcf.js +4 -4
  215. fides/ui-build/static/admin/lib/fides.js +4 -4
  216. fides/ui-build/static/admin/login/[provider].html +1 -1
  217. fides/ui-build/static/admin/login.html +1 -1
  218. fides/ui-build/static/admin/messaging/[id].html +1 -1
  219. fides/ui-build/static/admin/messaging/add-template.html +1 -1
  220. fides/ui-build/static/admin/messaging.html +1 -1
  221. fides/ui-build/static/admin/poc/ant-components.html +1 -1
  222. fides/ui-build/static/admin/poc/form-experiments/AntForm.html +1 -1
  223. fides/ui-build/static/admin/poc/form-experiments/FormikAntFormItem.html +1 -1
  224. fides/ui-build/static/admin/poc/form-experiments/FormikControlled.html +1 -1
  225. fides/ui-build/static/admin/poc/form-experiments/FormikField.html +1 -1
  226. fides/ui-build/static/admin/poc/form-experiments/FormikSpreadField.html +1 -1
  227. fides/ui-build/static/admin/poc/forms.html +1 -1
  228. fides/ui-build/static/admin/poc/table-migration.html +1 -1
  229. fides/ui-build/static/admin/privacy-requests/[id].html +1 -1
  230. fides/ui-build/static/admin/privacy-requests/configure/messaging.html +1 -1
  231. fides/ui-build/static/admin/privacy-requests/configure/storage.html +1 -1
  232. fides/ui-build/static/admin/privacy-requests/configure.html +1 -1
  233. fides/ui-build/static/admin/privacy-requests.html +1 -1
  234. fides/ui-build/static/admin/properties/[id].html +1 -1
  235. fides/ui-build/static/admin/properties/add-property.html +1 -1
  236. fides/ui-build/static/admin/properties.html +1 -1
  237. fides/ui-build/static/admin/reporting/datamap.html +1 -1
  238. fides/ui-build/static/admin/settings/about/alpha.html +1 -1
  239. fides/ui-build/static/admin/settings/about.html +1 -1
  240. fides/ui-build/static/admin/settings/consent/[configuration_id]/[purpose_id].html +1 -1
  241. fides/ui-build/static/admin/settings/consent.html +1 -1
  242. fides/ui-build/static/admin/settings/custom-fields.html +1 -1
  243. fides/ui-build/static/admin/settings/domain-records.html +1 -1
  244. fides/ui-build/static/admin/settings/domains.html +1 -1
  245. fides/ui-build/static/admin/settings/email-templates.html +1 -1
  246. fides/ui-build/static/admin/settings/locations.html +1 -1
  247. fides/ui-build/static/admin/settings/organization.html +1 -1
  248. fides/ui-build/static/admin/settings/regulations.html +1 -1
  249. fides/ui-build/static/admin/systems/configure/[id]/test-datasets.html +1 -1
  250. fides/ui-build/static/admin/systems/configure/[id].html +1 -1
  251. fides/ui-build/static/admin/systems.html +1 -1
  252. fides/ui-build/static/admin/taxonomy.html +1 -1
  253. fides/ui-build/static/admin/user-management/new.html +1 -1
  254. fides/ui-build/static/admin/user-management/profile/[id].html +1 -1
  255. fides/ui-build/static/admin/user-management.html +1 -1
  256. fides/ui-build/static/admin/_next/static/8108ANFxs99VY7KZ_Xev2/_buildManifest.js +0 -1
  257. fides/ui-build/static/admin/_next/static/chunks/1316-6cc72a45ebf7ff81.js +0 -1
  258. fides/ui-build/static/admin/_next/static/chunks/1807-3beab149351d5ded.js +0 -1
  259. fides/ui-build/static/admin/_next/static/chunks/1817-e601e737e3cc7a0e.js +0 -1
  260. fides/ui-build/static/admin/_next/static/chunks/255-7db55b0e3a0f9dea.js +0 -1
  261. fides/ui-build/static/admin/_next/static/chunks/2599-6c4d22e75028d8b6.js +0 -1
  262. fides/ui-build/static/admin/_next/static/chunks/2858-0b44609b6be7850b.js +0 -1
  263. fides/ui-build/static/admin/_next/static/chunks/2866-a73888c17a195cbe.js +0 -1
  264. fides/ui-build/static/admin/_next/static/chunks/3615-5e2d062d684b8fa1.js +0 -1
  265. fides/ui-build/static/admin/_next/static/chunks/409-a257e14acebcd73b.js +0 -1
  266. fides/ui-build/static/admin/_next/static/chunks/431-34f0b91c26f8d9ab.js +0 -1
  267. fides/ui-build/static/admin/_next/static/chunks/5309-b2c4803370634ff8.js +0 -1
  268. fides/ui-build/static/admin/_next/static/chunks/570-c99f07161bd339cd.js +0 -1
  269. fides/ui-build/static/admin/_next/static/chunks/6780-e3d40aa17a4bf2e9.js +0 -1
  270. fides/ui-build/static/admin/_next/static/chunks/6954-bb875d9ac89f6030.js +0 -1
  271. fides/ui-build/static/admin/_next/static/chunks/7062.fda15dcb7df85675.js +0 -1
  272. fides/ui-build/static/admin/_next/static/chunks/7c79804f.7a7112aece470725.js +0 -1
  273. fides/ui-build/static/admin/_next/static/chunks/9014-eeae6f581158e645.js +0 -1
  274. fides/ui-build/static/admin/_next/static/chunks/9046-5c4c22c375de25b1.js +0 -1
  275. fides/ui-build/static/admin/_next/static/chunks/9278-9b1b5970f0702668.js +0 -1
  276. fides/ui-build/static/admin/_next/static/chunks/9392.f4520f66206d347d.js +0 -1
  277. fides/ui-build/static/admin/_next/static/chunks/ea076c0a.84423f606aef37cd.js +0 -1
  278. fides/ui-build/static/admin/_next/static/chunks/pages/consent/reporting-afdbd4665657cfa1.js +0 -1
  279. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-2265ecb899d45fbc.js +0 -1
  280. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]-5d522637871ac6c8.js +0 -1
  281. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-9ddb52ebb7ac4c71.js +0 -1
  282. fides/ui-build/static/admin/_next/static/chunks/pages/datamap-7674b97d655c193b.js +0 -1
  283. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-0a58aee2d1e7fa01.js +0 -1
  284. fides/ui-build/static/admin/_next/static/chunks/pages/messaging-5094ffea13f32ed9.js +0 -1
  285. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-32600543eb7b584f.js +0 -1
  286. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-10ce53ea356f8bad.js +0 -1
  287. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-5501bbb129fee9c4.js +0 -1
  288. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-cbe4c8f9096b6543.js +0 -1
  289. fides/ui-build/static/admin/_next/static/chunks/pages/reporting/datamap-e130c0197362e8f3.js +0 -1
  290. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-6387fcc8cce872eb.js +0 -1
  291. fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/[id]-ff5738706da07801.js +0 -1
  292. fides/ui-build/static/admin/_next/static/chunks/webpack-ff0cd6bff75588da.js +0 -1
  293. fides/ui-build/static/admin/_next/static/css/2cadb5f62dcd7c2b.css +0 -1
  294. {ethyca_fides-2.66.2rc0.dist-info → ethyca_fides-2.67.0.dist-info}/WHEEL +0 -0
  295. {ethyca_fides-2.66.2rc0.dist-info → ethyca_fides-2.67.0.dist-info}/entry_points.txt +0 -0
  296. {ethyca_fides-2.66.2rc0.dist-info → ethyca_fides-2.67.0.dist-info}/licenses/LICENSE +0 -0
  297. {ethyca_fides-2.66.2rc0.dist-info → ethyca_fides-2.67.0.dist-info}/top_level.txt +0 -0
  298. /fides/ui-build/static/admin/_next/static/{8108ANFxs99VY7KZ_Xev2 → MNlh9olWjgbqAHKyQY3LF}/_ssgManifest.js +0 -0
  299. /fides/ui-build/static/admin/_next/static/chunks/{2921-455e6357b74d2f76.js → 2921-86f1547ac40a5cdf.js} +0 -0
  300. /fides/ui-build/static/admin/_next/static/chunks/{3923-6cc911dafccc5f63.js → 3923-13a6b4da2d51bf8f.js} +0 -0
  301. /fides/ui-build/static/admin/_next/static/chunks/{401-1b529d5800aa1f3a.js → 401-3cc1fee61494e3bd.js} +0 -0
  302. /fides/ui-build/static/admin/_next/static/chunks/{5574-b13021775a15bfd2.js → 5574-9312f97b637d9ee2.js} +0 -0
  303. /fides/ui-build/static/admin/_next/static/chunks/{7630-9aac73191ed5ed13.js → 7630-b1c93688013ef013.js} +0 -0
  304. /fides/ui-build/static/admin/_next/static/chunks/{9826-111aaee8bd8dbd09.js → 9826-3c578665c6d3b21d.js} +0 -0
  305. /fides/ui-build/static/admin/_next/static/chunks/pages/{404-aece2c920ea14514.js → 404-2d803dab6a00f353.js} +0 -0
  306. /fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{multiple-dc75dc6e37e52f05.js → multiple-8ff7f37913ad736a.js} +0 -0
  307. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure/{add-vendors-24d226b5a8de5c74.js → add-vendors-d00c9034cdeb0236.js} +0 -0
  308. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{configure-6a8ef51138ac926a.js → configure-0e1ca0f4c8e7f4da.js} +0 -0
  309. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{properties-6f86ab63a08a6528.js → properties-057cad65e7414a44.js} +0 -0
  310. /fides/ui-build/static/admin/_next/static/chunks/pages/{consent-73d3cbf68f7c3a31.js → consent-e17c56eec8d91371.js} +0 -0
  311. /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/{[projectUrn]-6ba9e160dae64695.js → [projectUrn]-80a6cc8e8573514a.js} +0 -0
  312. /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{resources-7648bbd4f6711e4d.js → resources-6c3714ee97a718c1.js} +0 -0
  313. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/detection/{[resourceUrn]-393e20924c83373e.js → [resourceUrn]-31e6c54794a9883e.js} +0 -0
  314. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{detection-8733807dad4bc96e.js → detection-2822a423a7ad0550.js} +0 -0
  315. /fides/ui-build/static/admin/_next/static/chunks/pages/dataset/{[datasetId]-006b695e5af5ef24.js → [datasetId]-a8e8b5f4ee7af86c.js} +0 -0
  316. /fides/ui-build/static/admin/_next/static/chunks/pages/{datastore-connection-c391c6fad56eec48.js → datastore-connection-3bd77864da523d41.js} +0 -0
  317. /fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{[id]-53fecfb9dd6a1e0c.js → [id]-5627d0d0668077f9.js} +0 -0
  318. /fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{add-template-76b01cec5fde10a9.js → add-template-feca66ad5c5fe54a.js} +0 -0
  319. /fides/ui-build/static/admin/_next/static/chunks/pages/poc/{ant-components-5c08e8447c45ce44.js → ant-components-64a322d01aae5ca7.js} +0 -0
  320. /fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{AntForm-06ad5f34585480aa.js → AntForm-8bca16a7726e7eb2.js} +0 -0
  321. /fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikAntFormItem-6f071c2bc9446cb0.js → FormikAntFormItem-b0f246fc3b67ebf7.js} +0 -0
  322. /fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikControlled-efcc38c58991ac9e.js → FormikControlled-1a0852b090bfc392.js} +0 -0
  323. /fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikField-430ba5c979abfb7c.js → FormikField-11f3de1b45e36583.js} +0 -0
  324. /fides/ui-build/static/admin/_next/static/chunks/pages/poc/{forms-5c561880bf131afb.js → forms-1b73a1c2b6c6285f.js} +0 -0
  325. /fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/{configure-d888a69a3bbe040e.js → configure-e551a860ec727802.js} +0 -0
  326. /fides/ui-build/static/admin/_next/static/chunks/pages/properties/{[id]-d3d8e3d7583ec635.js → [id]-dd99183f93763ae4.js} +0 -0
  327. /fides/ui-build/static/admin/_next/static/chunks/pages/properties/{add-property-1af10ed303815d46.js → add-property-0bdbc1fcbf553b8f.js} +0 -0
  328. /fides/ui-build/static/admin/_next/static/chunks/pages/{properties-cebc0dc186be499a.js → properties-e959378bb32b6b73.js} +0 -0
  329. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/about/{alpha-5e1322de868d615e.js → alpha-1066f0c202ef744c.js} +0 -0
  330. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{about-241f95e372b65d0f.js → about-37ba24a72a06862e.js} +0 -0
  331. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domain-records-41242f805599feda.js → domain-records-51333dbd21cb37c8.js} +0 -0
  332. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domains-2e885f74c92f669c.js → domains-bde86e5f6c09da5a.js} +0 -0
  333. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{email-templates-ff112655ad5f41e5.js → email-templates-4f9a5cc8bea7725b.js} +0 -0
  334. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{regulations-86062a18e081a52a.js → regulations-102efd9199e87124.js} +0 -0
  335. /fides/ui-build/static/admin/_next/static/chunks/pages/user-management/{new-a2524414e968f862.js → new-de8cb3739ab99c09.js} +0 -0
@@ -14,6 +14,7 @@ from fides.api.common_exceptions import (
14
14
  ClientUnsuccessfulException,
15
15
  IdentityNotFoundException,
16
16
  ManualWebhookFieldsUnset,
17
+ MaskingSecretsExpired,
17
18
  MessageDispatchException,
18
19
  NoCachedManualWebhookEntry,
19
20
  PrivacyRequestExit,
@@ -75,9 +76,11 @@ from fides.api.task.graph_task import (
75
76
  from fides.api.task.manual.manual_task_utils import create_manual_task_artificial_graphs
76
77
  from fides.api.tasks import DatabaseTask, celery_app
77
78
  from fides.api.tasks.scheduled.scheduler import scheduler
79
+ from fides.api.util.cache import get_all_masking_secret_keys
78
80
  from fides.api.util.collection_util import Row
79
81
  from fides.api.util.logger import Pii, _log_exception, _log_warning
80
82
  from fides.api.util.logger_context_utils import LoggerContextKeys, log_context
83
+ from fides.api.util.memory_watchdog import memory_limiter
81
84
  from fides.common.api.v1.urn_registry import (
82
85
  PRIVACY_REQUEST_TRANSFER_TO_PARENT,
83
86
  V1_URL_PREFIX,
@@ -356,8 +359,8 @@ def upload_and_save_access_results( # pylint: disable=R0912
356
359
 
357
360
 
358
361
  @celery_app.task(base=DatabaseTask, bind=True)
359
- # TODO: Add log_context back in, this is just for some temporary testing
360
- # @log_context(capture_args={"privacy_request_id": LoggerContextKeys.privacy_request_id})
362
+ @memory_limiter
363
+ @log_context(capture_args={"privacy_request_id": LoggerContextKeys.privacy_request_id})
361
364
  def run_privacy_request(
362
365
  self: DatabaseTask,
363
366
  privacy_request_id: str,
@@ -478,12 +481,21 @@ def run_privacy_request(
478
481
  connection_configs
479
482
  )
480
483
 
484
+ # If the privacy request requires manual finalization and has not yet been finalized, we exit here
485
+ if (
486
+ privacy_request.status
487
+ == PrivacyRequestStatus.requires_manual_finalization
488
+ and privacy_request.finalized_at is None
489
+ ):
490
+ return
491
+
481
492
  # Access CHECKPOINT
482
493
  if (
483
494
  policy.get_rules_for_action(action_type=ActionType.access)
484
495
  or policy.get_rules_for_action(action_type=ActionType.erasure)
485
496
  ) and can_run_checkpoint(
486
- request_checkpoint=CurrentStep.access, from_checkpoint=resume_step
497
+ request_checkpoint=CurrentStep.access,
498
+ from_checkpoint=resume_step,
487
499
  ):
488
500
  privacy_request.cache_failed_checkpoint_details(CurrentStep.access)
489
501
  access_runner(
@@ -528,9 +540,12 @@ def run_privacy_request(
528
540
  if policy.get_rules_for_action(
529
541
  action_type=ActionType.erasure
530
542
  ) and can_run_checkpoint(
531
- request_checkpoint=CurrentStep.erasure, from_checkpoint=resume_step
543
+ request_checkpoint=CurrentStep.erasure,
544
+ from_checkpoint=resume_step,
532
545
  ):
533
546
  privacy_request.cache_failed_checkpoint_details(CurrentStep.erasure)
547
+ _verify_masking_secrets(policy, privacy_request, resume_step)
548
+
534
549
  # We only need to run the erasure once until masking strategies are handled
535
550
  erasure_runner(
536
551
  privacy_request=privacy_request,
@@ -652,58 +667,111 @@ def run_privacy_request(
652
667
  if not proceed:
653
668
  return
654
669
 
655
- legacy_request_completion_enabled = ConfigProxy(
656
- session
657
- ).notifications.send_request_completion_notification
658
-
659
- action_type = (
660
- MessagingActionType.PRIVACY_REQUEST_COMPLETE_ACCESS
661
- if policy.get_rules_for_action(action_type=ActionType.access)
662
- else MessagingActionType.PRIVACY_REQUEST_COMPLETE_DELETION
663
- )
664
-
665
- if message_send_enabled(
666
- session,
667
- privacy_request.property_id,
668
- action_type,
669
- legacy_request_completion_enabled,
670
- ) and not policy.get_rules_for_action(action_type=ActionType.consent):
671
- try:
672
- if not access_result_urls:
673
- # For DSR 3.0, if the request had both access and erasure rules, this needs to be fetched
674
- # from the database because the Privacy Request would have exited
675
- # processing and lost access to the access_result_urls in memory
676
- access_result_urls = (
677
- privacy_request.access_result_urls or {}
678
- ).get("access_result_urls", [])
679
- initiate_privacy_request_completion_email(
680
- session,
681
- policy,
682
- access_result_urls,
683
- identity_data,
684
- privacy_request.property_id,
685
- )
686
- except (IdentityNotFoundException, MessageDispatchException) as e:
687
- privacy_request.error_processing(db=session)
688
- # If dev mode, log traceback
689
- _log_exception(e, CONFIG.dev_mode)
690
- return
691
-
692
- # Only mark as complete if not in error state
693
- if privacy_request.status != PrivacyRequestStatus.error:
694
- privacy_request.finished_processing_at = datetime.utcnow()
695
- AuditLog.create(
696
- db=session,
697
- data={
698
- "user_id": "system",
699
- "privacy_request_id": privacy_request.id,
700
- "action": AuditLogAction.finished,
701
- "message": "",
702
- },
670
+ # Request finalization CHECKPOINT
671
+ if can_run_checkpoint(
672
+ request_checkpoint=CurrentStep.finalization,
673
+ from_checkpoint=resume_step,
674
+ ):
675
+ privacy_request.cache_failed_checkpoint_details(
676
+ CurrentStep.finalization,
703
677
  )
704
- privacy_request.status = PrivacyRequestStatus.complete
705
- logger.info("Privacy request run completed.")
706
- privacy_request.save(db=session)
678
+ if privacy_request.status != PrivacyRequestStatus.error:
679
+ erasure_rules = policy.get_rules_for_action(
680
+ action_type=ActionType.erasure
681
+ )
682
+ if (
683
+ privacy_request.finalized_at is None
684
+ and erasure_rules
685
+ and CONFIG.execution.erasure_request_finalization_required
686
+ ):
687
+ logger.info(
688
+ "Marking privacy request '{}' as requires manual finalization.",
689
+ privacy_request.id,
690
+ )
691
+ privacy_request.status = (
692
+ PrivacyRequestStatus.requires_manual_finalization
693
+ )
694
+ privacy_request.save(db=session)
695
+ return
696
+
697
+ # Finally, mark the request as complete
698
+ if privacy_request.finalized_at:
699
+ logger.info(
700
+ "Marking privacy request '{}' as finalized.",
701
+ privacy_request.id,
702
+ )
703
+ privacy_request.add_success_execution_log(
704
+ session,
705
+ connection_key=None,
706
+ dataset_name="Request finalized",
707
+ collection_name=None,
708
+ message=f"Request finalized for privacy request: {privacy_request.id}",
709
+ action_type=privacy_request.policy.get_action_type(), # type: ignore
710
+ )
711
+
712
+ logger.info(
713
+ "Marking privacy request '{}' as complete.",
714
+ privacy_request.id,
715
+ )
716
+ AuditLog.create(
717
+ db=session,
718
+ data={
719
+ "user_id": "system",
720
+ "privacy_request_id": privacy_request.id,
721
+ "action": AuditLogAction.finished,
722
+ "message": "",
723
+ },
724
+ )
725
+ privacy_request.status = PrivacyRequestStatus.complete
726
+ privacy_request.finished_processing_at = datetime.utcnow()
727
+ privacy_request.save(db=session)
728
+
729
+ # Send a final email to the user confirming request completion
730
+ if privacy_request.status == PrivacyRequestStatus.complete:
731
+ legacy_request_completion_enabled = ConfigProxy(
732
+ session
733
+ ).notifications.send_request_completion_notification
734
+
735
+ action_type = (
736
+ MessagingActionType.PRIVACY_REQUEST_COMPLETE_ACCESS
737
+ if policy.get_rules_for_action(
738
+ action_type=ActionType.access
739
+ )
740
+ else MessagingActionType.PRIVACY_REQUEST_COMPLETE_DELETION
741
+ )
742
+
743
+ if message_send_enabled(
744
+ session,
745
+ privacy_request.property_id,
746
+ action_type,
747
+ legacy_request_completion_enabled,
748
+ ) and not policy.get_rules_for_action(
749
+ action_type=ActionType.consent
750
+ ):
751
+ if not access_result_urls:
752
+ # For DSR 3.0, if the request had both access and erasure rules, this needs to be fetched
753
+ # from the database because the Privacy Request would have exited
754
+ # processing and lost access to the access_result_urls in memory
755
+ access_result_urls = (
756
+ privacy_request.access_result_urls or {}
757
+ ).get("access_result_urls", [])
758
+
759
+ try:
760
+ initiate_privacy_request_completion_email(
761
+ session,
762
+ policy,
763
+ access_result_urls,
764
+ identity_data,
765
+ privacy_request.property_id,
766
+ )
767
+ except (
768
+ IdentityNotFoundException,
769
+ MessageDispatchException,
770
+ ) as e:
771
+ privacy_request.error_processing(db=session)
772
+ # If dev mode, log traceback
773
+ _log_exception(e, CONFIG.dev_mode)
774
+ return
707
775
 
708
776
 
709
777
  def initiate_privacy_request_completion_email(
@@ -1000,3 +1068,25 @@ def run_webhooks_and_report_status(
1000
1068
  return False
1001
1069
 
1002
1070
  return True
1071
+
1072
+
1073
+ def _verify_masking_secrets(
1074
+ policy: Policy, privacy_request: PrivacyRequest, resume_step: Optional[CurrentStep]
1075
+ ) -> None:
1076
+ """
1077
+ Checks that the required masking secrets are still cached for the given request.
1078
+ Raises an exception if masking secrets are needed for the given policy but they don't exist.
1079
+ """
1080
+
1081
+ if resume_step is None:
1082
+ return
1083
+
1084
+ # if masking can be performed without any masking secrets, we skip the cache check
1085
+ if (
1086
+ policy.generate_masking_secrets()
1087
+ and not get_all_masking_secret_keys(privacy_request.id)
1088
+ and not privacy_request.masking_secrets
1089
+ ):
1090
+ raise MaskingSecretsExpired(
1091
+ f"The masking secrets for privacy request ID '{privacy_request.id}' have expired. Please submit a new erasure request."
1092
+ )
@@ -8,10 +8,10 @@ from typing import Any, Dict, List, Optional, Set
8
8
  from httpx import AsyncClient
9
9
  from loguru import logger
10
10
  from sqlalchemy import text
11
+ from sqlalchemy.orm import Session
11
12
  from sqlalchemy.sql.elements import TextClause
12
13
 
13
14
  from fides.api.common_exceptions import PrivacyRequestNotFound
14
- from fides.api.models.policy import Policy
15
15
  from fides.api.models.privacy_request import (
16
16
  EXITED_EXECUTION_LOG_STATUSES,
17
17
  PrivacyRequest,
@@ -19,14 +19,12 @@ from fides.api.models.privacy_request import (
19
19
  )
20
20
  from fides.api.models.worker_task import ExecutionLogStatus
21
21
  from fides.api.schemas.drp_privacy_request import DrpPrivacyRequestCreate
22
- from fides.api.schemas.masking.masking_secrets import MaskingSecretCache
23
22
  from fides.api.schemas.policy import ActionType
24
23
  from fides.api.schemas.privacy_request import (
25
24
  PrivacyRequestResponse,
26
25
  PrivacyRequestStatus,
27
26
  )
28
27
  from fides.api.schemas.redis_cache import Identity
29
- from fides.api.service.masking.strategy.masking_strategy import MaskingStrategy
30
28
  from fides.api.tasks import DSR_QUEUE_NAME, DatabaseTask, celery_app
31
29
  from fides.api.tasks.scheduled.scheduler import scheduler
32
30
  from fides.api.util.cache import (
@@ -34,6 +32,9 @@ from fides.api.util.cache import (
34
32
  celery_tasks_in_flight,
35
33
  get_async_task_tracking_cache_key,
36
34
  get_cache,
35
+ get_privacy_request_retry_count,
36
+ increment_privacy_request_retry_count,
37
+ reset_privacy_request_retry_count,
37
38
  )
38
39
  from fides.api.util.lock import redis_lock
39
40
  from fides.common.api.v1.urn_registry import PRIVACY_REQUESTS, V1_URL_PREFIX
@@ -69,7 +70,6 @@ def build_required_privacy_request_kwargs(
69
70
 
70
71
  def cache_data(
71
72
  privacy_request: PrivacyRequest,
72
- policy: Policy,
73
73
  identity: Identity,
74
74
  encryption_key: Optional[str],
75
75
  drp_request_body: Optional[DrpPrivacyRequestCreate],
@@ -82,23 +82,6 @@ def cache_data(
82
82
  privacy_request.cache_custom_privacy_request_fields(custom_privacy_request_fields)
83
83
  privacy_request.cache_encryption(encryption_key) # handles None already
84
84
 
85
- # Store masking secrets in the cache
86
- logger.info("Caching masking secrets for privacy request {}", privacy_request.id)
87
- erasure_rules = policy.get_rules_for_action(action_type=ActionType.erasure)
88
- unique_masking_strategies_by_name: Set[str] = set()
89
- for rule in erasure_rules:
90
- strategy_name: str = rule.masking_strategy["strategy"] # type: ignore
91
- configuration = rule.masking_strategy["configuration"] # type: ignore
92
- if strategy_name in unique_masking_strategies_by_name:
93
- continue
94
- unique_masking_strategies_by_name.add(strategy_name)
95
- masking_strategy = MaskingStrategy.get_strategy(strategy_name, configuration)
96
- if masking_strategy.secrets_required():
97
- masking_secrets: List[MaskingSecretCache] = (
98
- masking_strategy.generate_secrets_for_cache()
99
- )
100
- for masking_secret in masking_secrets:
101
- privacy_request.cache_masking_secret(masking_secret)
102
85
  if drp_request_body:
103
86
  privacy_request.cache_drp_request_body(drp_request_body)
104
87
 
@@ -371,10 +354,17 @@ def initiate_interrupted_task_requeue_poll() -> None:
371
354
 
372
355
 
373
356
  def get_cached_task_id(entity_id: str) -> Optional[str]:
374
- """Gets the cached task ID for a privacy request or request task by ID."""
357
+ """Gets the cached task ID for a privacy request or request task by ID.
358
+
359
+ Raises Exception if cache operations fail, allowing callers to handle cache failures appropriately.
360
+ """
375
361
  cache: FidesopsRedis = get_cache()
376
- task_id = cache.get(get_async_task_tracking_cache_key(entity_id))
377
- return task_id
362
+ try:
363
+ task_id = cache.get(get_async_task_tracking_cache_key(entity_id))
364
+ return task_id
365
+ except Exception as exc:
366
+ logger.error(f"Failed to get cached task ID for entity {entity_id}: {exc}")
367
+ raise
378
368
 
379
369
 
380
370
  REQUEUE_INTERRUPTED_TASKS_LOCK = "requeue_interrupted_tasks_lock"
@@ -414,6 +404,115 @@ def _get_task_ids_from_dsr_queue(
414
404
  return queued_tasks_ids
415
405
 
416
406
 
407
+ def _cancel_interrupted_tasks_and_error_privacy_request(
408
+ db: Session, privacy_request: PrivacyRequest, error_message: Optional[str] = None
409
+ ) -> None:
410
+ """
411
+ Cancel all tasks associated with an interrupted privacy request and set the privacy request to error state.
412
+
413
+ This function:
414
+ 1. Logs the error message (either provided or default)
415
+ 2. Revokes the main privacy request task and all associated request tasks
416
+ 3. Sets the privacy request status to error
417
+ 4. Creates an error log entry
418
+
419
+ Args:
420
+ db: Database session
421
+ privacy_request: The privacy request to cancel and error
422
+ error_message: Optional error message to log. If not provided, uses default message.
423
+ """
424
+ if error_message:
425
+ logger.error(error_message)
426
+ else:
427
+ logger.error(
428
+ f"Canceling interrupted tasks and marking privacy request {privacy_request.id} as error"
429
+ )
430
+
431
+ # Cancel all associated Celery tasks
432
+ privacy_request.cancel_celery_tasks()
433
+
434
+ # Set privacy request to error state using the existing method
435
+ try:
436
+ privacy_request.error_processing(db)
437
+ logger.info(
438
+ f"Privacy request {privacy_request.id} marked as error due to task interruption"
439
+ )
440
+ except Exception as exc:
441
+ logger.error(
442
+ f"Failed to mark privacy request {privacy_request.id} as error: {exc}"
443
+ )
444
+
445
+
446
+ def _handle_privacy_request_requeue(
447
+ db: Session, privacy_request: PrivacyRequest
448
+ ) -> None:
449
+ """Handle retry logic for a privacy request - either requeue or cancel based on retry count."""
450
+ try:
451
+ # Check retry count and either requeue or cancel based on limit
452
+ current_retry_count = get_privacy_request_retry_count(privacy_request.id)
453
+ max_retries = CONFIG.execution.privacy_request_requeue_retry_count
454
+
455
+ if current_retry_count < max_retries:
456
+ # Increment retry count and attempt requeue
457
+ new_retry_count = increment_privacy_request_retry_count(privacy_request.id)
458
+ logger.info(
459
+ f"Requeuing privacy request {privacy_request.id} "
460
+ f"(attempt {new_retry_count}/{max_retries})"
461
+ )
462
+
463
+ from fides.service.privacy_request.privacy_request_service import ( # pylint: disable=cyclic-import
464
+ PrivacyRequestError,
465
+ _requeue_privacy_request,
466
+ )
467
+
468
+ try:
469
+ _requeue_privacy_request(db, privacy_request)
470
+ except PrivacyRequestError as exc:
471
+ # If requeue fails, cancel tasks and set to error state
472
+ _cancel_interrupted_tasks_and_error_privacy_request(
473
+ db, privacy_request, exc.message
474
+ )
475
+ else:
476
+ # Exceeded retry limit, cancel tasks and set to error state
477
+ _cancel_interrupted_tasks_and_error_privacy_request(
478
+ db,
479
+ privacy_request,
480
+ f"Privacy request {privacy_request.id} exceeded max retry attempts "
481
+ f"({max_retries}), canceling tasks and setting to error state",
482
+ )
483
+ # Reset retry count since we're giving up
484
+ reset_privacy_request_retry_count(privacy_request.id)
485
+
486
+ except Exception as cache_exc:
487
+ # If cache operations fail (Redis down, network issues, etc.), fail safe by canceling
488
+ _cancel_interrupted_tasks_and_error_privacy_request(
489
+ db,
490
+ privacy_request,
491
+ f"Cache operation failed for privacy request {privacy_request.id}, "
492
+ f"failing safe by canceling tasks: {cache_exc}",
493
+ )
494
+
495
+
496
+ def _get_request_task_ids_in_progress(
497
+ db: Session, privacy_request_id: str
498
+ ) -> List[str]:
499
+ """Get the IDs of request tasks that are currently in progress for a privacy request."""
500
+ request_tasks_in_progress = (
501
+ db.query(RequestTask.id)
502
+ .filter(RequestTask.privacy_request_id == privacy_request_id)
503
+ .filter(
504
+ RequestTask.status.in_(
505
+ [
506
+ ExecutionLogStatus.in_processing,
507
+ ExecutionLogStatus.pending,
508
+ ]
509
+ )
510
+ )
511
+ .all()
512
+ )
513
+ return [task[0] for task in request_tasks_in_progress]
514
+
515
+
417
516
  # pylint: disable=too-many-branches
418
517
  @celery_app.task(base=DatabaseTask, bind=True)
419
518
  def requeue_interrupted_tasks(self: DatabaseTask) -> None:
@@ -463,17 +562,40 @@ def requeue_interrupted_tasks(self: DatabaseTask) -> None:
463
562
  )
464
563
 
465
564
  # Get task IDs from the queue in a memory-efficient way
466
- queued_tasks_ids = _get_task_ids_from_dsr_queue(redis_conn)
565
+ try:
566
+ queued_tasks_ids = _get_task_ids_from_dsr_queue(redis_conn)
567
+ except Exception as queue_exc:
568
+ logger.warning(
569
+ f"Failed to get task IDs from queue, skipping queue state checks: {queue_exc}"
570
+ )
571
+ return
467
572
 
468
573
  # Check each privacy request
469
574
  for privacy_request in in_progress_requests:
470
575
  should_requeue = False
471
576
  logger.debug(f"Checking tasks for privacy request {privacy_request.id}")
472
577
 
473
- task_id = get_cached_task_id(privacy_request.id)
578
+ try:
579
+ task_id = get_cached_task_id(privacy_request.id)
580
+ except Exception as cache_exc:
581
+ # If we can't get the task ID due to cache failure, fail safe by canceling
582
+ _cancel_interrupted_tasks_and_error_privacy_request(
583
+ db,
584
+ privacy_request,
585
+ f"Cache failure when getting task ID for privacy request {privacy_request.id}, "
586
+ f"failing safe by canceling tasks: {cache_exc}",
587
+ )
588
+ continue
474
589
 
475
590
  # If the task ID is not cached, we can't check if it's running
591
+ # This means the request is stuck - cancel it
476
592
  if not task_id:
593
+ _cancel_interrupted_tasks_and_error_privacy_request(
594
+ db,
595
+ privacy_request,
596
+ f"No task ID found for privacy request {privacy_request.id}, "
597
+ f"request is stuck without a running task - canceling",
598
+ )
477
599
  continue
478
600
 
479
601
  # Check if the main privacy request task is active
@@ -491,30 +613,36 @@ def requeue_interrupted_tasks(self: DatabaseTask) -> None:
491
613
  )
492
614
  should_requeue = True
493
615
 
494
- request_tasks_in_progress = (
495
- db.query(RequestTask.id)
496
- .filter(RequestTask.privacy_request_id == privacy_request.id)
497
- .filter(
498
- RequestTask.status.in_(
499
- [
500
- ExecutionLogStatus.in_processing,
501
- ExecutionLogStatus.pending,
502
- ]
503
- )
504
- )
505
- .all()
616
+ request_task_ids_in_progress = _get_request_task_ids_in_progress(
617
+ db, privacy_request.id
506
618
  )
507
- request_task_ids_in_progress = [
508
- task[0] for task in request_tasks_in_progress
509
- ]
510
619
 
511
620
  # Check each individual request task
512
621
  for request_task_id in request_task_ids_in_progress:
513
- subtask_id = get_cached_task_id(request_task_id)
622
+ try:
623
+ subtask_id = get_cached_task_id(request_task_id)
624
+ except Exception as cache_exc:
625
+ # If we can't get the subtask ID due to cache failure, fail safe by canceling
626
+ _cancel_interrupted_tasks_and_error_privacy_request(
627
+ db,
628
+ privacy_request,
629
+ f"Cache failure when getting subtask ID for request task {request_task_id} "
630
+ f"(privacy request {privacy_request.id}), failing safe by canceling tasks: {cache_exc}",
631
+ )
632
+ should_requeue = False
633
+ break
514
634
 
515
635
  # If the task ID is not cached, we can't check if it's running
636
+ # This means the subtask is stuck - cancel the entire privacy request
516
637
  if not subtask_id:
517
- continue
638
+ _cancel_interrupted_tasks_and_error_privacy_request(
639
+ db,
640
+ privacy_request,
641
+ f"No task ID found for request task {request_task_id} "
642
+ f"(privacy request {privacy_request.id}), subtask is stuck - canceling privacy request",
643
+ )
644
+ should_requeue = False
645
+ break
518
646
 
519
647
  if (
520
648
  subtask_id not in queued_tasks_ids
@@ -528,12 +656,4 @@ def requeue_interrupted_tasks(self: DatabaseTask) -> None:
528
656
 
529
657
  # Requeue the privacy request if needed
530
658
  if should_requeue:
531
- from fides.service.privacy_request.privacy_request_service import ( # pylint: disable=cyclic-import
532
- PrivacyRequestError,
533
- _requeue_privacy_request,
534
- )
535
-
536
- try:
537
- _requeue_privacy_request(db, privacy_request)
538
- except PrivacyRequestError as exc:
539
- logger.error(exc.message)
659
+ _handle_privacy_request_requeue(db, privacy_request)
File without changes
@@ -0,0 +1,109 @@
1
+ import operator as py_operator
2
+ from typing import Any, Union
3
+
4
+ from loguru import logger
5
+ from sqlalchemy.orm import Session
6
+
7
+ from fides.api.graph.config import FieldPath
8
+ from fides.api.task.conditional_dependencies.schemas import (
9
+ Condition,
10
+ ConditionGroup,
11
+ ConditionLeaf,
12
+ GroupOperator,
13
+ Operator,
14
+ )
15
+
16
+ operator_methods = {
17
+ Operator.exists: lambda a, _: a is not None,
18
+ Operator.not_exists: lambda a, _: a is None,
19
+ Operator.eq: py_operator.eq,
20
+ Operator.neq: py_operator.ne,
21
+ Operator.lt: lambda a, b: a < b if a is not None else False,
22
+ Operator.lte: lambda a, b: a <= b if a is not None else False,
23
+ Operator.gt: lambda a, b: a > b if a is not None else False,
24
+ Operator.gte: lambda a, b: a >= b if a is not None else False,
25
+ Operator.list_contains: lambda a, b: b in a if isinstance(a, list) else False,
26
+ Operator.not_in_list: lambda a, b: a not in b if isinstance(b, list) else True,
27
+ }
28
+
29
+
30
+ class ConditionEvaluator:
31
+ """Evaluates nested conditions for manual task creation"""
32
+
33
+ def __init__(self, db: Session):
34
+ self.db = db
35
+
36
+ def evaluate_rule(self, rule: Condition, data: Union[dict, Any]) -> bool:
37
+ """Evaluate a nested condition rule against input data"""
38
+ if isinstance(rule, ConditionLeaf):
39
+ return self._evaluate_leaf_condition(rule, data)
40
+ # ConditionGroup
41
+ return self._evaluate_group_condition(rule, data)
42
+
43
+ def _evaluate_leaf_condition(
44
+ self, condition: ConditionLeaf, data: Union[dict, Any]
45
+ ) -> bool:
46
+ """Evaluate a leaf condition against input data"""
47
+ actual_value = self._get_nested_value(data, condition.field_address.split("."))
48
+ # Apply operator and return result
49
+ return self._apply_operator(actual_value, condition.operator, condition.value)
50
+
51
+ def _evaluate_group_condition(
52
+ self, group: ConditionGroup, data: Union[dict, Any]
53
+ ) -> bool:
54
+ """Evaluate a group condition against input data"""
55
+ results = [
56
+ self.evaluate_rule(condition, data) for condition in group.conditions
57
+ ]
58
+
59
+ logical_operators = {GroupOperator.and_: all, GroupOperator.or_: any}
60
+ operator_func = logical_operators.get(group.logical_operator)
61
+
62
+ if operator_func is None:
63
+ logger.warning(f"Unknown logical operator: {group.logical_operator}")
64
+ return False
65
+
66
+ return operator_func(results)
67
+
68
+ def _get_nested_value(self, data: Union[dict, Any], keys: list[str]) -> Any:
69
+ """Get nested value from data using dot notation
70
+
71
+ Supports both simple dictionary access and Fides reference structures:
72
+ - Simple dict: data["user"]["name"]
73
+ - Fides FieldAddress: data.get_field_value(FieldAddress("dataset", "collection", "field_address"))
74
+ - Fides Collection: data.get_field_value(FieldPath("field_address", "subfield"))
75
+ """
76
+ if not keys:
77
+ return data
78
+
79
+ current = data
80
+
81
+ # Try Fides reference structures first
82
+ if hasattr(current, "get_field_value"):
83
+ try:
84
+ field_path = FieldPath(*keys) if len(keys) > 1 else FieldPath(keys[0])
85
+ return current.get_field_value(field_path)
86
+ except (AttributeError, ValueError):
87
+ pass
88
+
89
+ # Fall back to dictionary access
90
+ for key in keys:
91
+ if not isinstance(current, dict):
92
+ current = current.get(key, {}) if hasattr(current, "get") else None
93
+ else:
94
+ current = current.get(key, {})
95
+
96
+ return current if current != {} else None
97
+
98
+ def _apply_operator(
99
+ self, actual_value: Any, operator: Operator, expected_value: Any
100
+ ) -> bool:
101
+ """Apply operator to actual and expected values"""
102
+
103
+ # Get the method for the operator and execute it
104
+ operator_method = operator_methods.get(operator)
105
+ if operator_method is None:
106
+ logger.warning(f"Unknown operator: {operator}")
107
+ return False
108
+
109
+ return operator_method(actual_value, expected_value)