ethyca-fides 2.66.1rc0__py2.py3-none-any.whl → 2.66.2b1__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 (276) hide show
  1. {ethyca_fides-2.66.1rc0.dist-info → ethyca_fides-2.66.2b1.dist-info}/METADATA +1 -1
  2. {ethyca_fides-2.66.1rc0.dist-info → ethyca_fides-2.66.2b1.dist-info}/RECORD +264 -254
  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 +4 -0
  13. fides/api/db/base.py +1 -0
  14. fides/api/db/database.py +1 -1
  15. fides/api/graph/execution.py +30 -0
  16. fides/api/models/manual_task/__init__.py +2 -0
  17. fides/api/models/manual_task/conditional_dependency.py +144 -0
  18. fides/api/models/{manual_task.py → manual_task/manual_task.py} +10 -0
  19. fides/api/models/masking_secret.py +72 -0
  20. fides/api/models/policy.py +23 -0
  21. fides/api/models/privacy_request/execution_log.py +1 -0
  22. fides/api/models/privacy_request/privacy_request.py +31 -13
  23. fides/api/oauth/roles.py +2 -0
  24. fides/api/schemas/application_config.py +11 -1
  25. fides/api/schemas/masking/masking_secrets.py +1 -1
  26. fides/api/schemas/policy.py +1 -0
  27. fides/api/schemas/privacy_request.py +5 -0
  28. fides/api/service/connectors/base_connector.py +1 -0
  29. fides/api/service/connectors/bigquery_connector.py +67 -19
  30. fides/api/service/connectors/dynamodb_connector.py +2 -1
  31. fides/api/service/connectors/fides_connector.py +1 -0
  32. fides/api/service/connectors/http_connector.py +1 -0
  33. fides/api/service/connectors/manual_task_connector.py +1 -0
  34. fides/api/service/connectors/manual_webhook_connector.py +2 -1
  35. fides/api/service/connectors/mongodb_connector.py +1 -0
  36. fides/api/service/connectors/okta_connector.py +1 -0
  37. fides/api/service/connectors/query_configs/bigquery_query_config.py +91 -32
  38. fides/api/service/connectors/rds_mysql_connector.py +1 -0
  39. fides/api/service/connectors/rds_postgres_connector.py +1 -0
  40. fides/api/service/connectors/s3_connector.py +1 -0
  41. fides/api/service/connectors/saas_connector.py +1 -0
  42. fides/api/service/connectors/scylla_connector.py +1 -0
  43. fides/api/service/connectors/sql_connector.py +36 -4
  44. fides/api/service/connectors/website_connector.py +1 -0
  45. fides/api/service/privacy_request/request_runner_service.py +142 -53
  46. fides/api/service/privacy_request/request_service.py +1 -22
  47. fides/api/task/conditional_dependencies/__init__.py +0 -0
  48. fides/api/task/conditional_dependencies/evaluator.py +109 -0
  49. fides/api/task/conditional_dependencies/schemas.py +54 -0
  50. fides/api/task/deprecated_graph_task.py +24 -6
  51. fides/api/task/execute_request_tasks.py +88 -11
  52. fides/api/task/graph_task.py +38 -3
  53. fides/api/task/manual/manual_task_graph_task.py +1 -0
  54. fides/api/util/cache.py +5 -0
  55. fides/api/util/encryption/secrets_util.py +48 -18
  56. fides/common/api/scope_registry.py +3 -0
  57. fides/common/api/v1/urn_registry.py +1 -1
  58. fides/config/execution_settings.py +4 -0
  59. fides/config/utils.py +1 -0
  60. fides/service/privacy_request/privacy_request_service.py +6 -1
  61. fides/ui-build/static/admin/404.html +1 -1
  62. fides/ui-build/static/admin/_next/static/CQD5hIjm-4lH18YYESYuD/_buildManifest.js +1 -0
  63. fides/ui-build/static/admin/_next/static/chunks/1817-6f35f58cd08b04ae.js +1 -0
  64. fides/ui-build/static/admin/_next/static/chunks/{203-5a663f465ba26bb4.js → 203-4e777c324a01dbec.js} +1 -1
  65. fides/ui-build/static/admin/_next/static/chunks/431-ade3e312fac3430b.js +1 -0
  66. fides/ui-build/static/admin/_next/static/chunks/6780-4b687168dd8daa84.js +1 -0
  67. fides/ui-build/static/admin/_next/static/chunks/8237-55049f8f5fd5e058.js +1 -0
  68. fides/ui-build/static/admin/_next/static/chunks/pages/{_app-39ccb07327c2c5d5.js → _app-be7889cec5a0f5cd.js} +56 -56
  69. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-71579a199158952e.js +1 -0
  70. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]-7e63ac744c45f6da.js +1 -0
  71. fides/ui-build/static/admin/_next/static/chunks/pages/{integrations-e2d5d7e2a5265e68.js → integrations-f10a7dcf7541c865.js} +1 -1
  72. fides/ui-build/static/admin/_next/static/chunks/pages/poc/{table-migration-69ad86b7a8a9a115.js → table-migration-05616e2ae20ff4f8.js} +1 -1
  73. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-1caa552a8f11f2f2.js +1 -0
  74. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-7498d1d5974a78b0.js +1 -0
  75. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-2d3a2d967767a131.js +1 -0
  76. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-6a9068df48bdee05.js +1 -0
  77. fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/[id]-fe58cebba358119d.js +1 -0
  78. fides/ui-build/static/admin/_next/static/css/{5bfb2473e5701527.css → 23cf870196941c9a.css} +1 -1
  79. fides/ui-build/static/admin/_next/static/css/b81194f2c3930152.css +1 -0
  80. fides/ui-build/static/admin/add-systems/manual.html +1 -1
  81. fides/ui-build/static/admin/add-systems/multiple.html +1 -1
  82. fides/ui-build/static/admin/add-systems.html +1 -1
  83. fides/ui-build/static/admin/consent/configure/add-vendors.html +1 -1
  84. fides/ui-build/static/admin/consent/configure.html +1 -1
  85. fides/ui-build/static/admin/consent/privacy-experience/[id].html +1 -1
  86. fides/ui-build/static/admin/consent/privacy-experience/new.html +1 -1
  87. fides/ui-build/static/admin/consent/privacy-experience.html +1 -1
  88. fides/ui-build/static/admin/consent/privacy-notices/[id].html +1 -1
  89. fides/ui-build/static/admin/consent/privacy-notices/new.html +1 -1
  90. fides/ui-build/static/admin/consent/privacy-notices.html +1 -1
  91. fides/ui-build/static/admin/consent/properties.html +1 -1
  92. fides/ui-build/static/admin/consent/reporting.html +1 -1
  93. fides/ui-build/static/admin/consent.html +1 -1
  94. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn].html +1 -1
  95. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn].html +1 -1
  96. fides/ui-build/static/admin/data-catalog/[systemId]/projects.html +1 -1
  97. fides/ui-build/static/admin/data-catalog/[systemId]/resources/[resourceUrn].html +1 -1
  98. fides/ui-build/static/admin/data-catalog/[systemId]/resources.html +1 -1
  99. fides/ui-build/static/admin/data-catalog.html +1 -1
  100. fides/ui-build/static/admin/data-discovery/action-center/[monitorId]/[systemId].html +1 -1
  101. fides/ui-build/static/admin/data-discovery/action-center/[monitorId].html +1 -1
  102. fides/ui-build/static/admin/data-discovery/action-center.html +1 -1
  103. fides/ui-build/static/admin/data-discovery/activity.html +1 -1
  104. fides/ui-build/static/admin/data-discovery/detection/[resourceUrn].html +1 -1
  105. fides/ui-build/static/admin/data-discovery/detection.html +1 -1
  106. fides/ui-build/static/admin/data-discovery/discovery/[resourceUrn].html +1 -1
  107. fides/ui-build/static/admin/data-discovery/discovery.html +1 -1
  108. fides/ui-build/static/admin/datamap.html +1 -1
  109. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName]/[...subfieldNames].html +1 -1
  110. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName].html +1 -1
  111. fides/ui-build/static/admin/dataset/[datasetId].html +1 -1
  112. fides/ui-build/static/admin/dataset/new.html +1 -1
  113. fides/ui-build/static/admin/dataset.html +1 -1
  114. fides/ui-build/static/admin/datastore-connection/[id].html +1 -1
  115. fides/ui-build/static/admin/datastore-connection/new.html +1 -1
  116. fides/ui-build/static/admin/datastore-connection.html +1 -1
  117. fides/ui-build/static/admin/index.html +1 -1
  118. fides/ui-build/static/admin/integrations/[id].html +1 -1
  119. fides/ui-build/static/admin/integrations.html +1 -1
  120. fides/ui-build/static/admin/lib/fides-ext-gpp.js +1 -1
  121. fides/ui-build/static/admin/lib/fides-headless.js +1 -1
  122. fides/ui-build/static/admin/lib/fides-preview.js +1 -1
  123. fides/ui-build/static/admin/lib/fides-tcf.js +3 -3
  124. fides/ui-build/static/admin/lib/fides.js +3 -3
  125. fides/ui-build/static/admin/login/[provider].html +1 -1
  126. fides/ui-build/static/admin/login.html +1 -1
  127. fides/ui-build/static/admin/messaging/[id].html +1 -1
  128. fides/ui-build/static/admin/messaging/add-template.html +1 -1
  129. fides/ui-build/static/admin/messaging.html +1 -1
  130. fides/ui-build/static/admin/poc/ant-components.html +1 -1
  131. fides/ui-build/static/admin/poc/form-experiments/AntForm.html +1 -1
  132. fides/ui-build/static/admin/poc/form-experiments/FormikAntFormItem.html +1 -1
  133. fides/ui-build/static/admin/poc/form-experiments/FormikControlled.html +1 -1
  134. fides/ui-build/static/admin/poc/form-experiments/FormikField.html +1 -1
  135. fides/ui-build/static/admin/poc/form-experiments/FormikSpreadField.html +1 -1
  136. fides/ui-build/static/admin/poc/forms.html +1 -1
  137. fides/ui-build/static/admin/poc/table-migration.html +1 -1
  138. fides/ui-build/static/admin/privacy-requests/[id].html +1 -1
  139. fides/ui-build/static/admin/privacy-requests/configure/messaging.html +1 -1
  140. fides/ui-build/static/admin/privacy-requests/configure/storage.html +1 -1
  141. fides/ui-build/static/admin/privacy-requests/configure.html +1 -1
  142. fides/ui-build/static/admin/privacy-requests.html +1 -1
  143. fides/ui-build/static/admin/properties/[id].html +1 -1
  144. fides/ui-build/static/admin/properties/add-property.html +1 -1
  145. fides/ui-build/static/admin/properties.html +1 -1
  146. fides/ui-build/static/admin/reporting/datamap.html +1 -1
  147. fides/ui-build/static/admin/settings/about/alpha.html +1 -1
  148. fides/ui-build/static/admin/settings/about.html +1 -1
  149. fides/ui-build/static/admin/settings/consent/[configuration_id]/[purpose_id].html +1 -1
  150. fides/ui-build/static/admin/settings/consent.html +1 -1
  151. fides/ui-build/static/admin/settings/custom-fields.html +1 -1
  152. fides/ui-build/static/admin/settings/domain-records.html +1 -1
  153. fides/ui-build/static/admin/settings/domains.html +1 -1
  154. fides/ui-build/static/admin/settings/email-templates.html +1 -1
  155. fides/ui-build/static/admin/settings/locations.html +1 -1
  156. fides/ui-build/static/admin/settings/organization.html +1 -1
  157. fides/ui-build/static/admin/settings/regulations.html +1 -1
  158. fides/ui-build/static/admin/systems/configure/[id]/test-datasets.html +1 -1
  159. fides/ui-build/static/admin/systems/configure/[id].html +1 -1
  160. fides/ui-build/static/admin/systems.html +1 -1
  161. fides/ui-build/static/admin/taxonomy.html +1 -1
  162. fides/ui-build/static/admin/user-management/new.html +1 -1
  163. fides/ui-build/static/admin/user-management/profile/[id].html +1 -1
  164. fides/ui-build/static/admin/user-management.html +1 -1
  165. fides/ui-build/static/admin/_next/static/IeU4qLtEtRJo0FsaIFIr8/_buildManifest.js +0 -1
  166. fides/ui-build/static/admin/_next/static/chunks/1817-e601e737e3cc7a0e.js +0 -1
  167. fides/ui-build/static/admin/_next/static/chunks/431-34f0b91c26f8d9ab.js +0 -1
  168. fides/ui-build/static/admin/_next/static/chunks/6780-5bd185892f6af46e.js +0 -1
  169. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-2265ecb899d45fbc.js +0 -1
  170. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]-8ab33a1e0272df1f.js +0 -1
  171. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-32600543eb7b584f.js +0 -1
  172. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-10ce53ea356f8bad.js +0 -1
  173. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-5501bbb129fee9c4.js +0 -1
  174. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-cbe4c8f9096b6543.js +0 -1
  175. fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/[id]-ff5738706da07801.js +0 -1
  176. fides/ui-build/static/admin/_next/static/css/2cadb5f62dcd7c2b.css +0 -1
  177. {ethyca_fides-2.66.1rc0.dist-info → ethyca_fides-2.66.2b1.dist-info}/WHEEL +0 -0
  178. {ethyca_fides-2.66.1rc0.dist-info → ethyca_fides-2.66.2b1.dist-info}/entry_points.txt +0 -0
  179. {ethyca_fides-2.66.1rc0.dist-info → ethyca_fides-2.66.2b1.dist-info}/licenses/LICENSE +0 -0
  180. {ethyca_fides-2.66.1rc0.dist-info → ethyca_fides-2.66.2b1.dist-info}/top_level.txt +0 -0
  181. /fides/ui-build/static/admin/_next/static/{IeU4qLtEtRJo0FsaIFIr8 → CQD5hIjm-4lH18YYESYuD}/_ssgManifest.js +0 -0
  182. /fides/ui-build/static/admin/_next/static/chunks/{2921-455e6357b74d2f76.js → 2921-86f1547ac40a5cdf.js} +0 -0
  183. /fides/ui-build/static/admin/_next/static/chunks/{3450-0ba194991d0cca88.js → 3450-1cc2bb07ed142203.js} +0 -0
  184. /fides/ui-build/static/admin/_next/static/chunks/{3855-e172870d3e21b0dd.js → 3855-e2fa6db53d32c3de.js} +0 -0
  185. /fides/ui-build/static/admin/_next/static/chunks/{3872-46cebf7ec1b31a2b.js → 3872-84b7e380b88b4454.js} +0 -0
  186. /fides/ui-build/static/admin/_next/static/chunks/{3923-6cc911dafccc5f63.js → 3923-13a6b4da2d51bf8f.js} +0 -0
  187. /fides/ui-build/static/admin/_next/static/chunks/{401-1b529d5800aa1f3a.js → 401-3cc1fee61494e3bd.js} +0 -0
  188. /fides/ui-build/static/admin/_next/static/chunks/{409-a257e14acebcd73b.js → 409-45a125437261580c.js} +0 -0
  189. /fides/ui-build/static/admin/_next/static/chunks/{4121-2bc09fc4ddbfe5cb.js → 4121-f50675521dfee6eb.js} +0 -0
  190. /fides/ui-build/static/admin/_next/static/chunks/{4230-60100f7ef3ddcde1.js → 4230-840c287045c88b34.js} +0 -0
  191. /fides/ui-build/static/admin/_next/static/chunks/{4608-bbb7bf511a05c3c2.js → 4608-a8e3100e2806dbff.js} +0 -0
  192. /fides/ui-build/static/admin/_next/static/chunks/{5309-d73339f062763fed.js → 5309-67bdf9001531e972.js} +0 -0
  193. /fides/ui-build/static/admin/_next/static/chunks/{5574-b13021775a15bfd2.js → 5574-9312f97b637d9ee2.js} +0 -0
  194. /fides/ui-build/static/admin/_next/static/chunks/{6084-7178ff6ea6822475.js → 6084-5d7598b7bcb548cf.js} +0 -0
  195. /fides/ui-build/static/admin/_next/static/chunks/{6662-507be5d46e5b719b.js → 6662-efb2cf74641647f2.js} +0 -0
  196. /fides/ui-build/static/admin/_next/static/chunks/{6853-2ad3e08fe6f9f5f2.js → 6853-4f8bf6558f8c6a46.js} +0 -0
  197. /fides/ui-build/static/admin/_next/static/chunks/{6882-6af16fef26c21e06.js → 6882-586b84aeb02d5830.js} +0 -0
  198. /fides/ui-build/static/admin/_next/static/chunks/{6954-bb875d9ac89f6030.js → 6954-34e062e4bffc7e71.js} +0 -0
  199. /fides/ui-build/static/admin/_next/static/chunks/{7476-281ee9a8286556f3.js → 7476-d206c11823c91088.js} +0 -0
  200. /fides/ui-build/static/admin/_next/static/chunks/{7630-9aac73191ed5ed13.js → 7630-b1c93688013ef013.js} +0 -0
  201. /fides/ui-build/static/admin/_next/static/chunks/{787-fb41002f797eb2df.js → 787-cbe2d0bfb513d90a.js} +0 -0
  202. /fides/ui-build/static/admin/_next/static/chunks/{79-7e87aff851423d4a.js → 79-3db1941d274f40c7.js} +0 -0
  203. /fides/ui-build/static/admin/_next/static/chunks/{796-329a5f823ec258a5.js → 796-98d4bd68909fbe1e.js} +0 -0
  204. /fides/ui-build/static/admin/_next/static/chunks/{9046-ce9567c9074563e2.js → 9046-54877976a0529de2.js} +0 -0
  205. /fides/ui-build/static/admin/_next/static/chunks/{9226-746771d47dff6266.js → 9226-72ad691ca57b83ef.js} +0 -0
  206. /fides/ui-build/static/admin/_next/static/chunks/{9826-111aaee8bd8dbd09.js → 9826-3c578665c6d3b21d.js} +0 -0
  207. /fides/ui-build/static/admin/_next/static/chunks/{9951-9b753ad7c3f51bdf.js → 9951-595d0f1588215081.js} +0 -0
  208. /fides/ui-build/static/admin/_next/static/chunks/pages/{404-aece2c920ea14514.js → 404-2d803dab6a00f353.js} +0 -0
  209. /fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{manual-98777246bec9dc2a.js → manual-acb59f8b5e97512a.js} +0 -0
  210. /fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{multiple-dc75dc6e37e52f05.js → multiple-8ff7f37913ad736a.js} +0 -0
  211. /fides/ui-build/static/admin/_next/static/chunks/pages/{add-systems-a71c0aff4e0e6535.js → add-systems-0943633a8e422695.js} +0 -0
  212. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure/{add-vendors-24d226b5a8de5c74.js → add-vendors-d00c9034cdeb0236.js} +0 -0
  213. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{configure-6a8ef51138ac926a.js → configure-0e1ca0f4c8e7f4da.js} +0 -0
  214. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{[id]-1edf582ba3cd3bbb.js → [id]-fc3a011154a2e1de.js} +0 -0
  215. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-experience-685771e5f7196d87.js → privacy-experience-09d4408014bcfe1c.js} +0 -0
  216. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{[id]-6ccedc70dc447089.js → [id]-d67542783ef5ddac.js} +0 -0
  217. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{new-944bca1cc57985b5.js → new-3f20e8a316bb3d5b.js} +0 -0
  218. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-notices-84f4bd14ce8673bc.js → privacy-notices-23e9dcd4590312d2.js} +0 -0
  219. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{properties-6f86ab63a08a6528.js → properties-057cad65e7414a44.js} +0 -0
  220. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{reporting-afdbd4665657cfa1.js → reporting-8f891957c8944137.js} +0 -0
  221. /fides/ui-build/static/admin/_next/static/chunks/pages/{consent-73d3cbf68f7c3a31.js → consent-e17c56eec8d91371.js} +0 -0
  222. /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]/{[resourceUrn]-11d52f1570759c4d.js → [resourceUrn]-99c9092d65c94807.js} +0 -0
  223. /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/{[projectUrn]-6ba9e160dae64695.js → [projectUrn]-80a6cc8e8573514a.js} +0 -0
  224. /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{projects-32eac8bbd217615a.js → projects-774fecea22ba8852.js} +0 -0
  225. /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/resources/{[resourceUrn]-b83afa5565d0c84e.js → [resourceUrn]-f6bd6aff389cb9fe.js} +0 -0
  226. /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{resources-7648bbd4f6711e4d.js → resources-6c3714ee97a718c1.js} +0 -0
  227. /fides/ui-build/static/admin/_next/static/chunks/pages/{data-catalog-6f630d42ac9fb6b4.js → data-catalog-8a7f9285da66b965.js} +0 -0
  228. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{action-center-9ddb52ebb7ac4c71.js → action-center-85e140788e251272.js} +0 -0
  229. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{activity-9aa744d56cdacb0d.js → activity-5af9381f02b2aff6.js} +0 -0
  230. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/detection/{[resourceUrn]-393e20924c83373e.js → [resourceUrn]-31e6c54794a9883e.js} +0 -0
  231. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{detection-8733807dad4bc96e.js → detection-2822a423a7ad0550.js} +0 -0
  232. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/discovery/{[resourceUrn]-14bd7500362ff224.js → [resourceUrn]-6421ce247549c5d6.js} +0 -0
  233. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{discovery-9e7dfd5a6acc2e8f.js → discovery-3eac407ac5181a3c.js} +0 -0
  234. /fides/ui-build/static/admin/_next/static/chunks/pages/{datamap-7674b97d655c193b.js → datamap-d2b275d83089820d.js} +0 -0
  235. /fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/{[...subfieldNames]-c0d2bfd465df20e0.js → [...subfieldNames]-1c98bd0959d9570a.js} +0 -0
  236. /fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/{[collectionName]-28280a8a39a6e37c.js → [collectionName]-e548cabda7da32c9.js} +0 -0
  237. /fides/ui-build/static/admin/_next/static/chunks/pages/dataset/{[datasetId]-006b695e5af5ef24.js → [datasetId]-a8e8b5f4ee7af86c.js} +0 -0
  238. /fides/ui-build/static/admin/_next/static/chunks/pages/dataset/{new-82fb246d87e58ebd.js → new-513c862c3a707735.js} +0 -0
  239. /fides/ui-build/static/admin/_next/static/chunks/pages/{dataset-20165c31ab1bc7cf.js → dataset-747b7a13289f1cd7.js} +0 -0
  240. /fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{[id]-b4a6bcc87d126840.js → [id]-3d22525b3c327b2e.js} +0 -0
  241. /fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{new-f95d7b0bbfc58f5a.js → new-d2cad97495e86adb.js} +0 -0
  242. /fides/ui-build/static/admin/_next/static/chunks/pages/{datastore-connection-c391c6fad56eec48.js → datastore-connection-0f29b47402292070.js} +0 -0
  243. /fides/ui-build/static/admin/_next/static/chunks/pages/{index-1919aab9e5834b51.js → index-12ac3e317fc86f21.js} +0 -0
  244. /fides/ui-build/static/admin/_next/static/chunks/pages/integrations/{[id]-eacabe4a80cb8813.js → [id]-8d83a5518c00fcfc.js} +0 -0
  245. /fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{[id]-53fecfb9dd6a1e0c.js → [id]-5627d0d0668077f9.js} +0 -0
  246. /fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{add-template-76b01cec5fde10a9.js → add-template-feca66ad5c5fe54a.js} +0 -0
  247. /fides/ui-build/static/admin/_next/static/chunks/pages/{messaging-5094ffea13f32ed9.js → messaging-c1bd3e7adbe8d2d3.js} +0 -0
  248. /fides/ui-build/static/admin/_next/static/chunks/pages/poc/{ant-components-5c08e8447c45ce44.js → ant-components-64a322d01aae5ca7.js} +0 -0
  249. /fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{AntForm-06ad5f34585480aa.js → AntForm-8bca16a7726e7eb2.js} +0 -0
  250. /fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikAntFormItem-6f071c2bc9446cb0.js → FormikAntFormItem-b0f246fc3b67ebf7.js} +0 -0
  251. /fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikControlled-efcc38c58991ac9e.js → FormikControlled-1a0852b090bfc392.js} +0 -0
  252. /fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikField-430ba5c979abfb7c.js → FormikField-11f3de1b45e36583.js} +0 -0
  253. /fides/ui-build/static/admin/_next/static/chunks/pages/poc/{forms-5c561880bf131afb.js → forms-1b73a1c2b6c6285f.js} +0 -0
  254. /fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/{configure-d888a69a3bbe040e.js → configure-e551a860ec727802.js} +0 -0
  255. /fides/ui-build/static/admin/_next/static/chunks/pages/properties/{[id]-d3d8e3d7583ec635.js → [id]-dd99183f93763ae4.js} +0 -0
  256. /fides/ui-build/static/admin/_next/static/chunks/pages/properties/{add-property-1af10ed303815d46.js → add-property-0bdbc1fcbf553b8f.js} +0 -0
  257. /fides/ui-build/static/admin/_next/static/chunks/pages/{properties-cebc0dc186be499a.js → properties-e959378bb32b6b73.js} +0 -0
  258. /fides/ui-build/static/admin/_next/static/chunks/pages/reporting/{datamap-e130c0197362e8f3.js → datamap-2a98bd257edd8f47.js} +0 -0
  259. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/about/{alpha-5e1322de868d615e.js → alpha-8f98a4895e74725e.js} +0 -0
  260. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{about-241f95e372b65d0f.js → about-8155a35a62fdb5ae.js} +0 -0
  261. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent/[configuration_id]/{[purpose_id]-fc201657f4a782c7.js → [purpose_id]-668d74c041d74650.js} +0 -0
  262. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{consent-c2d39cba8396ef3a.js → consent-a989532a12c40dcf.js} +0 -0
  263. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{custom-fields-d992103cc55901ae.js → custom-fields-45bea76ff7eda3cb.js} +0 -0
  264. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domain-records-41242f805599feda.js → domain-records-51333dbd21cb37c8.js} +0 -0
  265. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domains-2e885f74c92f669c.js → domains-bde86e5f6c09da5a.js} +0 -0
  266. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{email-templates-ff112655ad5f41e5.js → email-templates-4f9a5cc8bea7725b.js} +0 -0
  267. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{locations-023e1895552817de.js → locations-6946e78a5d43e654.js} +0 -0
  268. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{organization-ac403c0886b20e20.js → organization-55a10e01dffc8039.js} +0 -0
  269. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{regulations-86062a18e081a52a.js → regulations-102efd9199e87124.js} +0 -0
  270. /fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/{test-datasets-7a3396ac819c7904.js → test-datasets-f91f22cf96566ed4.js} +0 -0
  271. /fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/{[id]-8314a819837f5b2a.js → [id]-d4a57ea18935dd70.js} +0 -0
  272. /fides/ui-build/static/admin/_next/static/chunks/pages/{systems-21f423a7c417aa9d.js → systems-648a0ff4920579ce.js} +0 -0
  273. /fides/ui-build/static/admin/_next/static/chunks/pages/{taxonomy-6387fcc8cce872eb.js → taxonomy-0b9d1a24188f65a9.js} +0 -0
  274. /fides/ui-build/static/admin/_next/static/chunks/pages/user-management/{new-a2524414e968f862.js → new-bc4eb541906781e6.js} +0 -0
  275. /fides/ui-build/static/admin/_next/static/chunks/pages/{user-management-173ac3a1ed2b05a6.js → user-management-45bfa04e45a7d13f.js} +0 -0
  276. /fides/ui-build/static/admin/_next/static/chunks/{webpack-ff0cd6bff75588da.js → webpack-63a0c45b150a1037.js} +0 -0
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)
@@ -0,0 +1,54 @@
1
+ from enum import Enum
2
+ from typing import List, Optional, Union
3
+
4
+ from pydantic import BaseModel, Field, model_validator
5
+
6
+
7
+ class Operator(str, Enum):
8
+ eq = "eq"
9
+ neq = "neq"
10
+ lt = "lt"
11
+ lte = "lte"
12
+ gt = "gt"
13
+ gte = "gte"
14
+ exists = "exists"
15
+ not_exists = "not_exists"
16
+ list_contains = "list_contains"
17
+ not_in_list = "not_in_list"
18
+
19
+
20
+ class GroupOperator(str, Enum):
21
+ and_ = "and"
22
+ or_ = "or"
23
+
24
+
25
+ # Leaf condition (e.g., "user.name exists", "user.created_at >= 2024-01-01")
26
+ class ConditionLeaf(BaseModel):
27
+ field_address: str = Field(
28
+ description="Field path to check (e.g., 'user.name', 'billing.subscription.status')"
29
+ )
30
+ operator: Operator = Field(description="Operator to apply")
31
+ value: Optional[
32
+ Union[str, int, float, bool, List[Union[str, int, float, bool]]]
33
+ ] = Field(default=None, description="Expected value for comparison")
34
+
35
+
36
+ # Nested logical condition (AND, OR)
37
+ class ConditionGroup(BaseModel):
38
+ logical_operator: GroupOperator = Field(
39
+ description="Logical operator: 'and' or 'or'"
40
+ )
41
+ conditions: list["Condition"] = Field(
42
+ description="List of conditions or nested groups"
43
+ )
44
+
45
+ @model_validator(mode="after")
46
+ def validate_conditions(self) -> "ConditionGroup":
47
+ if not self.conditions:
48
+ raise ValueError("conditions list cannot be empty")
49
+ return self
50
+
51
+
52
+ # Use model_rebuild to allow recursive nesting
53
+ Condition = Union[ConditionLeaf, ConditionGroup]
54
+ ConditionGroup.model_rebuild()
@@ -1,4 +1,5 @@
1
1
  # pylint: disable=too-many-lines
2
+ from functools import partial
2
3
  from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union
3
4
 
4
5
  import dask
@@ -252,16 +253,33 @@ def run_erasure_request_deprecated( # pylint: disable = too-many-arguments
252
253
 
253
254
  access_request_data[ROOT_COLLECTION_ADDRESS.value] = [identity]
254
255
 
255
- dsk: Dict[CollectionAddress, Any] = {
256
- k: (
257
- t.erasure_request,
256
+ # Build the dask task graph for erasure, ensuring we also pass along the
257
+ # upstream access data that may be required by the connector (e.g. BigQuery
258
+ # delete statements). We accomplish this by partially applying the
259
+ # `inputs` kwarg on each task's `erasure_request` method. The resulting
260
+ # callable accepts the original positional arguments expected by Dask.
261
+
262
+ dsk: Dict[CollectionAddress, Any] = {}
263
+ for k, t in env.items():
264
+ # Collect upstream access data in the same order as the input keys
265
+ upstream_access_data: List[List[Row]] = [
266
+ access_request_data.get(str(input_key), [])
267
+ for input_key in t.execution_node.input_keys
268
+ ]
269
+
270
+ # Bind the `inputs` keyword argument so it is supplied when the task executes
271
+ erasure_fn_with_inputs = partial(
272
+ t.erasure_request, inputs=upstream_access_data
273
+ )
274
+
275
+ # Build the task tuple: (callable, retrieved_data, *prereqs)
276
+ dsk[k] = (
277
+ erasure_fn_with_inputs,
258
278
  access_request_data.get(
259
279
  str(k), []
260
- ), # Pass in the results of the access request for this collection
280
+ ), # Data retrieved for this collection
261
281
  *_evaluate_erasure_dependencies(t, erasure_end_nodes),
262
282
  )
263
- for k, t in env.items()
264
- }
265
283
 
266
284
  # root node returns 0 to be consistent with the output of the other erasure tasks
267
285
  dsk[ROOT_COLLECTION_ADDRESS] = 0
@@ -298,17 +298,11 @@ def run_access_node(
298
298
  )
299
299
  # Currently, upstream tasks and "input keys" (which are built by data dependencies)
300
300
  # are the same, but they may not be the same in the future.
301
- ordered_upstream_tasks: List[Optional[RequestTask]] = (
302
- _order_tasks_by_input_key(
301
+ upstream_access_data: List[List[Row]] = (
302
+ _build_upstream_access_data(
303
303
  graph_task.execution_node.input_keys, upstream_results
304
304
  )
305
305
  )
306
- # Pass in access data dependencies in the same order as the input keys.
307
- # If we don't have access data for an upstream node, pass in an empty list
308
- upstream_access_data: List[List[Row]] = [
309
- upstream.get_access_data() if upstream else []
310
- for upstream in ordered_upstream_tasks
311
- ]
312
306
  # Run the main access function
313
307
  graph_task.access_request(*upstream_access_data)
314
308
 
@@ -359,7 +353,7 @@ def run_erasure_node(
359
353
  session,
360
354
  ) as resources:
361
355
  # Build GraphTask resource to facilitate execution
362
- graph_task: GraphTask = create_graph_task(
356
+ erasure_graph_task: GraphTask = create_graph_task(
363
357
  session, request_task, resources
364
358
  )
365
359
  # Get access data that was saved in the erasure format that was collected from the
@@ -368,8 +362,24 @@ def run_erasure_node(
368
362
  request_task.get_data_for_erasures() or []
369
363
  )
370
364
 
371
- # Run the main erasure function!
372
- graph_task.erasure_request(retrieved_data)
365
+ upstream_access_data: List[List[Row]] = []
366
+
367
+ try:
368
+ upstream_access_data = (
369
+ get_upstream_access_data_for_erasure_task(
370
+ request_task, session, resources
371
+ )
372
+ )
373
+ except Exception as e:
374
+ logger.error(
375
+ f"Unable to get upstream access data for erasure task {request_task.collection_address}: {e}"
376
+ )
377
+
378
+ # Run the main erasure function, passing along the upstream access data.
379
+ # The extra data is currently only needed for generating BigQuery delete statements.
380
+ erasure_graph_task.erasure_request(
381
+ retrieved_data, inputs=upstream_access_data
382
+ )
373
383
 
374
384
  queue_downstream_tasks_with_retries(
375
385
  self,
@@ -487,6 +497,73 @@ def _order_tasks_by_input_key(
487
497
  return tasks
488
498
 
489
499
 
500
+ def get_upstream_access_data_for_erasure_task(
501
+ erasure_request_task: RequestTask,
502
+ session: Session,
503
+ resources: TaskResources,
504
+ ) -> List[List[Row]]:
505
+ """
506
+ Retrieves upstream access data for a given erasure request task.
507
+
508
+ This function finds the corresponding access task for the erasure task,
509
+ creates a GraphTask to extract input keys, and builds the upstream access data
510
+ needed for erasure operations (particularly for BigQuery delete statements).
511
+
512
+ Args:
513
+ erasure_request_task: The erasure task that needs upstream access data
514
+ session: Database session for querying
515
+ resources: Task resources for creating GraphTask
516
+
517
+ Returns:
518
+ List[List[Row]]: Upstream access data ordered by input keys
519
+
520
+ Raises:
521
+ Exception: If the corresponding access task cannot be found
522
+ """
523
+ # Get the corresponding access task for the current erasure task
524
+ access_request_task = (
525
+ session.query(RequestTask)
526
+ .filter(
527
+ RequestTask.privacy_request_id == erasure_request_task.privacy_request_id,
528
+ RequestTask.collection_address == erasure_request_task.collection_address,
529
+ RequestTask.action_type == ActionType.access,
530
+ )
531
+ .first()
532
+ )
533
+
534
+ if not access_request_task:
535
+ raise Exception(
536
+ f"Unable to find access request task for erasure task {erasure_request_task.collection_address}"
537
+ )
538
+
539
+ # Convert the request task to a GraphTask to get the input_keys
540
+ access_graph_task: GraphTask = create_graph_task(
541
+ session, access_request_task, resources
542
+ )
543
+
544
+ # Build and return the upstream access data
545
+ return _build_upstream_access_data(
546
+ access_graph_task.execution_node.input_keys,
547
+ access_request_task.upstream_tasks_objects(session),
548
+ )
549
+
550
+
551
+ def _build_upstream_access_data(
552
+ input_keys: List[CollectionAddress],
553
+ upstream_tasks: Query,
554
+ ) -> List[List[Row]]:
555
+ """
556
+ Helper function to build the access data for the current node.
557
+ The access data is passed in the same order as the input keys.
558
+ If we don't have access data for an upstream node, return an empty list.
559
+ """
560
+
561
+ ordered_upstream: List[Optional[RequestTask]] = _order_tasks_by_input_key(
562
+ input_keys, upstream_tasks
563
+ )
564
+ return [task.get_access_data() if task else [] for task in ordered_upstream]
565
+
566
+
490
567
  mapping = {
491
568
  ActionType.access.value: run_access_node,
492
569
  ActionType.erasure.value: run_erasure_node,
@@ -421,6 +421,7 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
421
421
  action_type: ActionType,
422
422
  ex: Optional[BaseException] = None,
423
423
  success_override_msg: Optional[str] = None,
424
+ record_count: Optional[int] = None,
424
425
  ) -> None:
425
426
  """On completion activities"""
426
427
  if ex:
@@ -440,8 +441,23 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
440
441
  mark_current_and_downstream_nodes_as_failed(request_task, db)
441
442
  else:
442
443
  logger.info("Ending {}, {}", self.resources.request.id, self.key)
444
+
445
+ # Build standardized success message with record count
446
+ base_message = (
447
+ str(success_override_msg) if success_override_msg else "success"
448
+ )
449
+ if record_count is not None:
450
+ if action_type == ActionType.access:
451
+ message = f"{base_message} - retrieved {record_count} records"
452
+ elif action_type == ActionType.erasure:
453
+ message = f"{base_message} - masked {record_count} records"
454
+ else:
455
+ message = f"{base_message} - processed {record_count} records"
456
+ else:
457
+ message = base_message
458
+
443
459
  self.update_status(
444
- str(success_override_msg) if success_override_msg else "success",
460
+ message,
445
461
  build_affected_field_logs(
446
462
  self.execution_node, self.resources.policy, action_type
447
463
  ),
@@ -637,7 +653,11 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
637
653
  if messages:
638
654
  success_message = "\n".join(messages)
639
655
 
640
- self.log_end(ActionType.access, success_override_msg=success_message)
656
+ self.log_end(
657
+ ActionType.access,
658
+ success_override_msg=success_message,
659
+ record_count=len(filtered_output),
660
+ )
641
661
  return filtered_output
642
662
 
643
663
  @retry(action_type=ActionType.erasure, default_return=0)
@@ -645,9 +665,15 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
645
665
  self,
646
666
  retrieved_data: List[Row],
647
667
  *erasure_prereqs: int, # TODO Remove when we stop support for DSR 2.0. DSR 3.0 enforces with downstream_tasks.
668
+ inputs: Optional[
669
+ List[List[Row]]
670
+ ] = None, # Upstream data from corresponding access task
648
671
  ) -> int:
649
672
  """Run erasure request"""
650
673
 
674
+ if inputs is None:
675
+ inputs = []
676
+
651
677
  # if there is no primary key specified in the graph node configuration
652
678
  # note this in the execution log and perform no erasures on this node
653
679
  if (
@@ -694,6 +720,10 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
694
720
  )
695
721
  return 0
696
722
 
723
+ formatted_input_data: NodeInput = self.pre_process_input_data(
724
+ *inputs, group_dependent_fields=True
725
+ )
726
+
697
727
  # Use execution context to capture postprocessor messages
698
728
  with collect_execution_log_messages() as messages:
699
729
  output = self.connector.mask_data(
@@ -702,6 +732,7 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
702
732
  self.resources.request,
703
733
  self.resources.privacy_request_task,
704
734
  retrieved_data,
735
+ formatted_input_data,
705
736
  )
706
737
 
707
738
  if self.request_task.id:
@@ -720,7 +751,11 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
720
751
  if messages:
721
752
  success_message = "\n".join(messages)
722
753
 
723
- self.log_end(ActionType.erasure, success_override_msg=success_message)
754
+ self.log_end(
755
+ ActionType.erasure,
756
+ success_override_msg=success_message,
757
+ record_count=output,
758
+ )
724
759
  return output
725
760
 
726
761
  @retry(action_type=ActionType.consent, default_return=False)
@@ -268,6 +268,7 @@ class ManualTaskGraphTask(GraphTask):
268
268
  self,
269
269
  retrieved_data: List[Row],
270
270
  *erasure_prereqs: int, # noqa: D401, pylint: disable=unused-argument
271
+ inputs: Optional[List[List[Row]]] = None,
271
272
  ) -> int:
272
273
  """Execute manual-task-driven erasure logic.
273
274
 
fides/api/util/cache.py CHANGED
@@ -387,3 +387,8 @@ def get_queue_counts() -> Dict[str, int]:
387
387
  logger.critical(exception)
388
388
  queue_counts = {}
389
389
  return queue_counts
390
+
391
+
392
+ def get_all_masking_secret_keys(privacy_request_id: str) -> List[str]:
393
+ cache: FidesopsRedis = get_cache()
394
+ return cache.keys(f"id-{privacy_request_id}-masking-secret-*")
@@ -1,14 +1,17 @@
1
1
  import secrets
2
- from typing import Dict, List, Optional, TypeVar
2
+ from typing import Any, Dict, List, Optional, TypeVar
3
3
 
4
4
  from loguru import logger
5
5
 
6
+ from fides.api.db.session import get_db_session
7
+ from fides.api.models.masking_secret import MaskingSecret
6
8
  from fides.api.schemas.masking.masking_secrets import (
7
9
  MaskingSecretCache,
8
10
  MaskingSecretMeta,
9
11
  SecretType,
10
12
  )
11
13
  from fides.api.util.cache import get_cache, get_masking_secret_cache_key
14
+ from fides.config import CONFIG
12
15
 
13
16
  T = TypeVar("T")
14
17
 
@@ -21,12 +24,14 @@ class SecretsUtil:
21
24
  masking_secret_meta: MaskingSecretMeta[T],
22
25
  ) -> Optional[T]:
23
26
  if privacy_request_id is not None:
24
- secret = SecretsUtil._get_secret_from_cache(
25
- privacy_request_id, secret_type, masking_secret_meta
27
+ secret = SecretsUtil.get_masking_secret(
28
+ privacy_request_id=privacy_request_id,
29
+ masking_strategy=masking_secret_meta.masking_strategy,
30
+ secret_type=secret_type,
26
31
  )
27
32
  if not secret:
28
33
  logger.warning(
29
- "Secret type {} expected from cache but was not present for masking strategy {}",
34
+ "Secret type {} expected but was not present for masking strategy {}",
30
35
  secret_type,
31
36
  masking_secret_meta.masking_strategy,
32
37
  )
@@ -37,20 +42,6 @@ class SecretsUtil:
37
42
  masking_secret_meta.secret_length
38
43
  )
39
44
 
40
- @staticmethod
41
- def _get_secret_from_cache(
42
- privacy_request_id: str,
43
- secret_type: SecretType,
44
- masking_secret_meta: MaskingSecretMeta[T],
45
- ) -> Optional[T]:
46
- cache = get_cache()
47
- masking_secret_cache_key: str = get_masking_secret_cache_key(
48
- privacy_request_id=privacy_request_id,
49
- masking_strategy=masking_secret_meta.masking_strategy,
50
- secret_type=secret_type,
51
- )
52
- return cache.get_encoded_by_key(masking_secret_cache_key)
53
-
54
45
  @staticmethod
55
46
  def generate_secret_string(length: int) -> str:
56
47
  return secrets.token_urlsafe(length)
@@ -75,3 +66,42 @@ class SecretsUtil:
75
66
  )
76
67
  )
77
68
  return masking_secrets
69
+
70
+ @staticmethod
71
+ def get_masking_secret(
72
+ privacy_request_id: str,
73
+ masking_strategy: str,
74
+ secret_type: SecretType,
75
+ ) -> Optional[Any]:
76
+ """
77
+ Attempts to retrieve masking secret from cache first, then falls back to DB.
78
+ """
79
+ # TODO: get rid of the cache check after a few releases
80
+ # Try cache first
81
+ cache = get_cache()
82
+ cache_key = get_masking_secret_cache_key(
83
+ privacy_request_id=privacy_request_id,
84
+ masking_strategy=masking_strategy,
85
+ secret_type=secret_type,
86
+ )
87
+ secret = cache.get_encoded_by_key(cache_key)
88
+ if secret is not None:
89
+ return secret
90
+
91
+ # Cache miss - try database
92
+ session_local = get_db_session(CONFIG)
93
+ with session_local() as session:
94
+ masking_secret: MaskingSecret = (
95
+ session.query(MaskingSecret)
96
+ .filter(
97
+ MaskingSecret.privacy_request_id == privacy_request_id,
98
+ MaskingSecret.masking_strategy == masking_strategy,
99
+ MaskingSecret.secret_type == secret_type,
100
+ )
101
+ .first()
102
+ )
103
+
104
+ if not masking_secret:
105
+ return None
106
+
107
+ return masking_secret.get_secret()
@@ -51,6 +51,7 @@ PRIVACY_REQUEST_ACCESS_RESULTS = "privacy-request-access-results"
51
51
  PRIVACY_REQUEST_EMAIL_INTEGRATIONS = "privacy-request-email-integrations"
52
52
  PRIVACY_REQUEST_NOTIFICATIONS = "privacy-request-notifications"
53
53
  READ = "read"
54
+ READ_OWN = "read-own"
54
55
  REGISTER = "register"
55
56
  RESET = "reset"
56
57
  RESPOND = "respond"
@@ -226,6 +227,7 @@ TAXONOMY_DELETE = f"{TAXONOMY}:{DELETE}"
226
227
  USER_CREATE = f"{USER}:{CREATE}"
227
228
  USER_DELETE = f"{USER}:{DELETE}"
228
229
  USER_READ = f"{USER}:{READ}"
230
+ USER_READ_OWN = f"{USER}:{READ_OWN}"
229
231
  USER_UPDATE = f"{USER}:{UPDATE}"
230
232
  USER_PASSWORD_RESET = f"{USER}:{PASSWORD_RESET}"
231
233
 
@@ -354,6 +356,7 @@ SCOPE_DOCS = {
354
356
  USER_UPDATE: "Update users",
355
357
  USER_DELETE: "Remove users",
356
358
  USER_READ: "View users",
359
+ USER_READ_OWN: "View own user",
357
360
  USER_PASSWORD_RESET: "Reset another user's password",
358
361
  USER_PERMISSION_CREATE: "Create user permissions",
359
362
  USER_PERMISSION_UPDATE: "Update user permissions",
@@ -93,7 +93,7 @@ PRIVACY_REQUEST_ACCESS_RESULTS = "/privacy-request/{privacy_request_id}/access-r
93
93
  PRIVACY_REQUEST_FILTERED_RESULTS = (
94
94
  "/privacy-request/{privacy_request_id}/filtered-results"
95
95
  )
96
-
96
+ PRIVACY_REQUEST_FINALIZE = "/privacy-request/{privacy_request_id}/finalize"
97
97
  PRIVACY_REQUEST_VERIFY_IDENTITY = "/privacy-request/{privacy_request_id}/verify"
98
98
  PRIVACY_REQUEST_RESUME = "/privacy-request/{privacy_request_id}/resume"
99
99
  PRIVACY_REQUEST_NOTIFICATIONS = "/privacy-request/notification"
@@ -61,6 +61,10 @@ class ExecutionSettings(FidesSettings):
61
61
  default=False,
62
62
  description="Temporary flag to switch to using DSR 3.0 to process your tasks.",
63
63
  )
64
+ erasure_request_finalization_required: bool = Field(
65
+ default=False,
66
+ description="Whether erasure requests require an additional finalization step after all collections have been executed.",
67
+ )
64
68
  fuzzy_search_enabled: bool = Field(
65
69
  default=True,
66
70
  description="Whether fuzzy search is enabled for privacy request lookups.",
fides/config/utils.py CHANGED
@@ -61,6 +61,7 @@ CONFIG_KEY_ALLOWLIST = {
61
61
  "task_retry_backoff",
62
62
  "require_manual_request_approval",
63
63
  "subject_identity_verification_required",
64
+ "sql_dry_run",
64
65
  ],
65
66
  "storage": [
66
67
  "active_default_storage_type",
@@ -193,13 +193,18 @@ class PrivacyRequestService:
193
193
 
194
194
  cache_data(
195
195
  privacy_request,
196
- policy,
197
196
  privacy_request_data.identity,
198
197
  privacy_request_data.encryption_key,
199
198
  None,
200
199
  privacy_request_data.custom_privacy_request_fields,
201
200
  )
202
201
 
202
+ if masking_secrets := policy.generate_masking_secrets():
203
+ logger.info(
204
+ "Caching masking secrets for privacy request {}", privacy_request.id
205
+ )
206
+ privacy_request.persist_masking_secrets(masking_secrets)
207
+
203
208
  check_and_dispatch_error_notifications(db=self.db)
204
209
 
205
210
  _handle_notifications_and_processing(
@@ -1 +1 @@
1
- <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link data-next-font="" rel="preconnect" href="/" crossorigin="anonymous"/><link rel="preload" href="/_next/static/css/2cadb5f62dcd7c2b.css" as="style"/><link rel="stylesheet" href="/_next/static/css/2cadb5f62dcd7c2b.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-ff0cd6bff75588da.js" defer=""></script><script src="/_next/static/chunks/framework-c92fc3344e6fd165.js" defer=""></script><script src="/_next/static/chunks/main-090643377c8254e6.js" defer=""></script><script src="/_next/static/chunks/pages/_app-39ccb07327c2c5d5.js" defer=""></script><script src="/_next/static/chunks/pages/404-aece2c920ea14514.js" defer=""></script><script src="/_next/static/IeU4qLtEtRJo0FsaIFIr8/_buildManifest.js" defer=""></script><script src="/_next/static/IeU4qLtEtRJo0FsaIFIr8/_ssgManifest.js" defer=""></script><style>.data-ant-cssinjs-cache-path{content:"";}</style></head><body><div id="__next"><div style="height:100%;display:flex"></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/404","query":{},"buildId":"IeU4qLtEtRJo0FsaIFIr8","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link data-next-font="" rel="preconnect" href="/" crossorigin="anonymous"/><link rel="preload" href="/_next/static/css/b81194f2c3930152.css" as="style"/><link rel="stylesheet" href="/_next/static/css/b81194f2c3930152.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-63a0c45b150a1037.js" defer=""></script><script src="/_next/static/chunks/framework-c92fc3344e6fd165.js" defer=""></script><script src="/_next/static/chunks/main-090643377c8254e6.js" defer=""></script><script src="/_next/static/chunks/pages/_app-be7889cec5a0f5cd.js" defer=""></script><script src="/_next/static/chunks/pages/404-2d803dab6a00f353.js" defer=""></script><script src="/_next/static/CQD5hIjm-4lH18YYESYuD/_buildManifest.js" defer=""></script><script src="/_next/static/CQD5hIjm-4lH18YYESYuD/_ssgManifest.js" defer=""></script><style>.data-ant-cssinjs-cache-path{content:"";}</style></head><body><div id="__next"><div style="height:100%;display:flex"></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/404","query":{},"buildId":"CQD5hIjm-4lH18YYESYuD","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>