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
@@ -0,0 +1,144 @@
1
+ from enum import Enum
2
+ from typing import TYPE_CHECKING, Optional, Union
3
+
4
+ from sqlalchemy import Column, ForeignKey, Index, Integer, String
5
+ from sqlalchemy.dialects.postgresql import JSONB
6
+ from sqlalchemy.ext.declarative import declared_attr
7
+ from sqlalchemy.orm import Session, relationship
8
+
9
+ from fides.api.db.base_class import Base, FidesBase
10
+ from fides.api.db.util import EnumColumn
11
+ from fides.api.task.conditional_dependencies.schemas import (
12
+ ConditionGroup,
13
+ ConditionLeaf,
14
+ )
15
+
16
+ if TYPE_CHECKING:
17
+ from fides.api.models.manual_task.manual_task import ManualTask
18
+
19
+
20
+ class ManualTaskConditionalDependencyType(str, Enum):
21
+ """Enum for manual task conditional dependency types.
22
+
23
+ This enum defines the two types of nodes in a conditional dependency tree:
24
+
25
+ - leaf: A terminal node that represents a single condition (e.g., "user.age >= 18")
26
+ - group: A non-terminal node that groups multiple conditions with logical operators (AND/OR)
27
+
28
+ Examples:
29
+ leaf: Used for simple field comparisons like:
30
+ - "user.name exists"
31
+ - "user.age >= 18"
32
+ - "billing.subscription.status == 'active'"
33
+
34
+ group: Used to combine multiple conditions with logical operators:
35
+ - AND group: "user.age >= 18 AND user.active == true"
36
+ - OR group: "user.role == 'admin' OR user.verified == true"
37
+ - Nested groups: "(user.age >= 18 AND (user.role == 'admin' OR user.verified == true))"
38
+ """
39
+
40
+ leaf = "leaf"
41
+ group = "group"
42
+
43
+
44
+ class ManualTaskConditionalDependency(Base):
45
+ """Model for storing conditional dependencies."""
46
+
47
+ @declared_attr
48
+ def __tablename__(cls) -> str:
49
+ """Overriding base class method to set the table name."""
50
+ return "manual_task_conditional_dependency"
51
+
52
+ # We need to redefine it here so that self-referential relationships
53
+ # can properly reference the `id` column instead of the built-in Python function.
54
+ id = Column(String(255), primary_key=True, default=FidesBase.generate_uuid)
55
+
56
+ # Foreign key relationships
57
+ manual_task_id = Column(
58
+ String, ForeignKey("manual_task.id", ondelete="CASCADE"), nullable=False
59
+ )
60
+ parent_id = Column(
61
+ String,
62
+ ForeignKey("manual_task_conditional_dependency.id", ondelete="CASCADE"),
63
+ nullable=True,
64
+ )
65
+
66
+ # Condition metadata
67
+ condition_type = Column(
68
+ EnumColumn(ManualTaskConditionalDependencyType), nullable=False
69
+ ) # leaf or group
70
+ field_address = Column(String, nullable=True) # For leaf conditions
71
+ operator = Column(String, nullable=True) # For leaf conditions
72
+ value = Column(JSONB, nullable=True) # For leaf conditions
73
+ logical_operator = Column(String, nullable=True) # 'and' or 'or' for groups
74
+
75
+ # Ordering
76
+ sort_order = Column(Integer, nullable=False, default=0)
77
+
78
+ __table_args__ = (
79
+ Index("ix_manual_task_conditional_dependency_manual_task_id", "manual_task_id"),
80
+ Index("ix_manual_task_conditional_dependency_parent_id", "parent_id"),
81
+ Index("ix_manual_task_conditional_dependency_condition_type", "condition_type"),
82
+ Index("ix_manual_task_conditional_dependency_sort_order", "sort_order"),
83
+ )
84
+
85
+ # Relationships
86
+ task = relationship("ManualTask", back_populates="conditional_dependencies")
87
+ parent = relationship(
88
+ "ManualTaskConditionalDependency",
89
+ remote_side=[id],
90
+ back_populates="children",
91
+ foreign_keys=[parent_id],
92
+ )
93
+ children = relationship(
94
+ "ManualTaskConditionalDependency",
95
+ back_populates="parent",
96
+ cascade="all, delete-orphan",
97
+ foreign_keys=[parent_id],
98
+ )
99
+
100
+ def to_condition_leaf(self) -> ConditionLeaf:
101
+ """Convert to ConditionLeaf if this is a leaf condition"""
102
+ if self.condition_type != "leaf":
103
+ raise ValueError("Cannot convert group condition to leaf")
104
+
105
+ return ConditionLeaf(
106
+ field_address=self.field_address, operator=self.operator, value=self.value
107
+ )
108
+
109
+ def to_condition_group(self) -> ConditionGroup:
110
+ """Convert to ConditionGroup if this is a group condition"""
111
+ if self.condition_type != "group":
112
+ raise ValueError("Cannot convert leaf condition to group")
113
+
114
+ # Recursively build children
115
+ child_conditions = []
116
+ children_list = [child for child in self.children] # type: ignore[attr-defined]
117
+ for child in sorted(children_list, key=lambda x: x.sort_order):
118
+ if child.condition_type == "leaf":
119
+ child_conditions.append(child.to_condition_leaf())
120
+ else:
121
+ child_conditions.append(child.to_condition_group())
122
+
123
+ return ConditionGroup(
124
+ logical_operator=self.logical_operator, conditions=child_conditions
125
+ )
126
+
127
+ @classmethod
128
+ def get_root_condition(
129
+ cls, db: Session, manual_task_id: str
130
+ ) -> Optional[Union[ConditionLeaf, ConditionGroup]]:
131
+ """Get the root condition for a config"""
132
+ root = (
133
+ db.query(cls)
134
+ .filter(cls.manual_task_id == manual_task_id, cls.parent_id.is_(None))
135
+ .first()
136
+ )
137
+
138
+ if not root:
139
+ return None
140
+
141
+ if root.condition_type == "leaf":
142
+ return root.to_condition_leaf()
143
+
144
+ return root.to_condition_group()
@@ -26,6 +26,9 @@ from fides.api.schemas.base_class import FidesSchema
26
26
  if TYPE_CHECKING:
27
27
  from fides.api.models.attachment import Attachment
28
28
  from fides.api.models.fides_user import FidesUser
29
+ from fides.api.models.manual_task.conditional_dependency import (
30
+ ManualTaskConditionalDependency,
31
+ )
29
32
 
30
33
  # ------------------------------------------------------------
31
34
  # Enums
@@ -242,6 +245,13 @@ class ManualTask(Base):
242
245
  viewonly=True, # No cascade delete - submissions are historical data
243
246
  )
244
247
 
248
+ conditional_dependencies = relationship(
249
+ "ManualTaskConditionalDependency",
250
+ back_populates="task",
251
+ uselist=True,
252
+ cascade="all, delete-orphan",
253
+ )
254
+
245
255
  # Properties
246
256
  @property
247
257
  def assigned_users(self) -> list[str]:
@@ -0,0 +1,72 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Any, Union
4
+ from urllib.parse import unquote_to_bytes
5
+
6
+ from sqlalchemy import Column, ForeignKey, String
7
+ from sqlalchemy.ext.declarative import declared_attr
8
+ from sqlalchemy.orm import Session, relationship
9
+ from sqlalchemy_utils.types.encrypted.encrypted_type import (
10
+ AesGcmEngine,
11
+ StringEncryptedType,
12
+ )
13
+
14
+ from fides.api.db.base_class import Base, JSONTypeOverride
15
+ from fides.api.util.custom_json_encoder import ENCODED_BYTES_PREFIX
16
+ from fides.config import CONFIG
17
+
18
+ if TYPE_CHECKING:
19
+ from fides.api.models.privacy_request import PrivacyRequest
20
+
21
+
22
+ class MaskingSecret(Base):
23
+ """SQLAlchemy model for storing secret caching information"""
24
+
25
+ @declared_attr
26
+ def __tablename__(self) -> str:
27
+ return "masking_secret"
28
+
29
+ privacy_request_id = Column(
30
+ String, ForeignKey("privacyrequest.id", ondelete="CASCADE"), nullable=False
31
+ )
32
+ secret = Column(
33
+ StringEncryptedType(
34
+ JSONTypeOverride,
35
+ CONFIG.security.app_encryption_key,
36
+ AesGcmEngine,
37
+ "pkcs5",
38
+ ),
39
+ nullable=False,
40
+ )
41
+ masking_strategy = Column(String, nullable=False)
42
+ secret_type = Column(String, nullable=False)
43
+ privacy_request = relationship("PrivacyRequest", back_populates="masking_secrets")
44
+
45
+ def set_secret(self, secret: Union[str, bytes]) -> None:
46
+ """Set the secret value, handling both string and bytes types"""
47
+ if isinstance(secret, str):
48
+ self.secret = secret.encode("utf-8")
49
+ elif isinstance(secret, bytes):
50
+ self.secret = secret
51
+ else:
52
+ raise ValueError("Secret must be either string or bytes")
53
+
54
+ def get_secret(self) -> Union[str, bytes]:
55
+ """Retrieve the secret in its original type"""
56
+ secret = self.secret
57
+ if isinstance(secret, str) and secret.startswith(ENCODED_BYTES_PREFIX):
58
+ return unquote_to_bytes(secret)[len(ENCODED_BYTES_PREFIX) :]
59
+ return secret
60
+
61
+ @classmethod
62
+ def create(
63
+ cls,
64
+ db: Session,
65
+ *,
66
+ data: dict[str, Any],
67
+ check_name: bool = True,
68
+ ) -> "MaskingSecret":
69
+ """
70
+ Create a new masking secret. Handles both string and bytes secrets automatically, encrypting them for storage.
71
+ """
72
+ return super().create(db=db, data=data, check_name=check_name)
@@ -25,7 +25,9 @@ from fides.api.models.client import ClientDetail
25
25
  from fides.api.models.connectionconfig import ConnectionConfig
26
26
  from fides.api.models.sql_models import DataCategory # type: ignore
27
27
  from fides.api.models.storage import StorageConfig, get_active_default_storage_config
28
+ from fides.api.schemas.masking.masking_secrets import MaskingSecretCache
28
29
  from fides.api.schemas.policy import ActionType, DrpAction
30
+ from fides.api.service.masking.strategy.masking_strategy import MaskingStrategy
29
31
  from fides.api.util.data_category import _validate_data_category
30
32
  from fides.config import CONFIG
31
33
 
@@ -140,6 +142,27 @@ class Policy(Base):
140
142
  except IndexError:
141
143
  return None
142
144
 
145
+ def generate_masking_secrets(self) -> Optional[List[MaskingSecretCache]]:
146
+ """
147
+ Returns a list of masking secrets for the masking strategies in the policy.
148
+ """
149
+
150
+ masking_secrets: List[MaskingSecretCache] = []
151
+ erasure_rules = self.get_rules_for_action(action_type=ActionType.erasure)
152
+ unique_masking_strategies_by_name: Set[str] = set()
153
+ for rule in erasure_rules:
154
+ strategy_name: str = rule.masking_strategy["strategy"] # type: ignore
155
+ configuration = rule.masking_strategy["configuration"] # type: ignore
156
+ if strategy_name in unique_masking_strategies_by_name:
157
+ continue
158
+ unique_masking_strategies_by_name.add(strategy_name)
159
+ masking_strategy = MaskingStrategy.get_strategy(
160
+ strategy_name, configuration
161
+ )
162
+ if masking_strategy.secrets_required():
163
+ masking_secrets.extend(masking_strategy.generate_secrets_for_cache())
164
+ return masking_secrets
165
+
143
166
  def applies_to(self, node: "TraversalNode") -> bool:
144
167
  """
145
168
  Returns True if any data category in the traversal node starts with any of the policy's target categories.
@@ -24,6 +24,7 @@ EXECUTION_CHECKPOINTS = [
24
24
  CurrentStep.finalize_consent,
25
25
  CurrentStep.email_post_send,
26
26
  CurrentStep.post_webhooks,
27
+ CurrentStep.finalization,
27
28
  ]
28
29
 
29
30
  COMPLETED_EXECUTION_LOG_STATUSES = [
@@ -50,6 +50,7 @@ from fides.api.models.comment import Comment, CommentReference, CommentReference
50
50
  from fides.api.models.fides_user import FidesUser
51
51
  from fides.api.models.field_types import EncryptedLargeDataDescriptor
52
52
  from fides.api.models.manual_webhook import AccessManualWebhook
53
+ from fides.api.models.masking_secret import MaskingSecret
53
54
  from fides.api.models.policy import (
54
55
  Policy,
55
56
  PolicyPreWebhook,
@@ -98,7 +99,6 @@ from fides.api.util.cache import (
98
99
  get_drp_request_body_cache_key,
99
100
  get_encryption_cache_key,
100
101
  get_identity_cache_key,
101
- get_masking_secret_cache_key,
102
102
  )
103
103
  from fides.api.util.collection_util import Row, extract_key_for_address
104
104
  from fides.api.util.constants import API_DATE_FORMAT
@@ -145,6 +145,12 @@ class PrivacyRequest(
145
145
  ForeignKey(FidesUser.id_field_path, ondelete="SET NULL"),
146
146
  nullable=True,
147
147
  )
148
+ finalized_at = Column(DateTime(timezone=True), nullable=True)
149
+ finalized_by = Column(
150
+ String,
151
+ ForeignKey(FidesUser.id_field_path, ondelete="SET NULL"),
152
+ nullable=True,
153
+ )
148
154
  submitted_by = Column(
149
155
  String,
150
156
  ForeignKey(FidesUser.id_field_path, ondelete="SET NULL"),
@@ -289,6 +295,13 @@ class PrivacyRequest(
289
295
  order_by="RequestTask.created_at",
290
296
  )
291
297
 
298
+ masking_secrets: "RelationshipProperty[List[MaskingSecret]]" = relationship(
299
+ "MaskingSecret",
300
+ back_populates="privacy_request",
301
+ uselist=True,
302
+ passive_deletes="all",
303
+ )
304
+
292
305
  @property
293
306
  def days_left(self: PrivacyRequest) -> Union[int, None]:
294
307
  if self.due_date is None:
@@ -566,19 +579,24 @@ class PrivacyRequest(
566
579
  encryption_key,
567
580
  )
568
581
 
569
- def cache_masking_secret(self, masking_secret: MaskingSecretCache) -> None:
570
- """Sets masking encryption secrets in the Fides app cache if provided"""
571
- if not masking_secret:
582
+ def persist_masking_secrets(
583
+ self, masking_secrets: List[MaskingSecretCache]
584
+ ) -> None:
585
+ """Persists masking encryption secrets to database."""
586
+ if not masking_secrets:
572
587
  return
573
- cache: FidesopsRedis = get_cache()
574
- cache.set_with_autoexpire(
575
- get_masking_secret_cache_key(
576
- self.id,
577
- masking_strategy=masking_secret.masking_strategy,
578
- secret_type=masking_secret.secret_type,
579
- ),
580
- FidesopsRedis.encode_obj(masking_secret.secret),
581
- )
588
+
589
+ session = Session.object_session(self)
590
+ for masking_secret in masking_secrets:
591
+ MaskingSecret.create(
592
+ db=session,
593
+ data={
594
+ "privacy_request_id": self.id,
595
+ "secret": masking_secret.secret,
596
+ "masking_strategy": masking_secret.masking_strategy,
597
+ "secret_type": masking_secret.secret_type,
598
+ },
599
+ )
582
600
 
583
601
  def get_cached_identity_data(self) -> Dict[str, Any]:
584
602
  """Retrieves any identity data pertaining to this request from the cache"""
fides/api/oauth/roles.py CHANGED
@@ -47,6 +47,7 @@ from fides.common.api.scope_registry import (
47
47
  SYSTEM_READ,
48
48
  USER_PERMISSION_ASSIGN_OWNERS,
49
49
  USER_READ,
50
+ USER_READ_OWN,
50
51
  WEBHOOK_READ,
51
52
  )
52
53
 
@@ -126,6 +127,7 @@ viewer_scopes = [ # Intentionally omitted USER_PERMISSION_READ and PRIVACY_REQU
126
127
 
127
128
  respondent_scopes = [
128
129
  PRIVACY_REQUEST_MANUAL_STEPS_RESPOND, # allows respondents to respond to assigned manual steps
130
+ USER_READ_OWN,
129
131
  ]
130
132
 
131
133
  external_respondent_scopes = [
@@ -11,6 +11,14 @@ from fides.api.schemas.messaging.messaging import MessagingServiceType
11
11
  from fides.config.admin_ui_settings import ErrorNotificationMode
12
12
 
13
13
 
14
+ class SqlDryRunMode(str, Enum):
15
+ """SQL dry run mode for controlling execution of SQL statements in privacy requests"""
16
+
17
+ none = "none"
18
+ access = "access"
19
+ erasure = "erasure"
20
+
21
+
14
22
  class StorageTypeApiAccepted(Enum):
15
23
  """Enum for storage destination types accepted in API updates"""
16
24
 
@@ -62,7 +70,9 @@ class ExecutionApplicationConfig(FidesSchema):
62
70
  subject_identity_verification_required: Optional[bool] = None
63
71
  disable_consent_identity_verification: Optional[bool] = None
64
72
  require_manual_request_approval: Optional[bool] = None
65
- model_config = ConfigDict(extra="forbid")
73
+ sql_dry_run: Optional[SqlDryRunMode] = None
74
+
75
+ model_config = ConfigDict(use_enum_values=True, extra="forbid")
66
76
 
67
77
 
68
78
  class AdminUIConfig(FidesSchema):
@@ -5,7 +5,7 @@ from typing import Callable, Generic, TypeVar
5
5
  T = TypeVar("T")
6
6
 
7
7
 
8
- class SecretType(Enum):
8
+ class SecretType(str, Enum):
9
9
  """Enum that holds all possible types of secrets across all masking strategies"""
10
10
 
11
11
  key = "key"
@@ -28,6 +28,7 @@ class CurrentStep(EnumType):
28
28
  finalize_consent = "finalize_consent"
29
29
  email_post_send = "email_post_send"
30
30
  post_webhooks = "post_webhooks"
31
+ finalization = "finalization"
31
32
 
32
33
 
33
34
  # action types we actively support in policies/requests
@@ -124,6 +124,8 @@ class PrivacyRequestResubmit(PrivacyRequestCreate):
124
124
  identity_verified_at: Optional[datetime] = None
125
125
  custom_privacy_request_fields_approved_at: Optional[datetime] = None
126
126
  custom_privacy_request_fields_approved_by: Optional[str] = None
127
+ finalized_at: Optional[datetime] = None
128
+ finalized_by: Optional[str] = None
127
129
 
128
130
 
129
131
  class ConsentRequestCreate(FidesSchema):
@@ -287,6 +289,7 @@ class PrivacyRequestStatus(str, EnumType):
287
289
  complete = "complete"
288
290
  paused = "paused"
289
291
  awaiting_email_send = "awaiting_email_send"
292
+ requires_manual_finalization = "requires_manual_finalization"
290
293
  canceled = "canceled"
291
294
  error = "error"
292
295
 
@@ -320,6 +323,8 @@ class PrivacyRequestResponse(FidesSchema):
320
323
  source: Optional[PrivacyRequestSource] = None
321
324
  deleted_at: Optional[datetime] = None
322
325
  deleted_by: Optional[str] = None
326
+ finalized_at: Optional[datetime] = None
327
+ finalized_by: Optional[str] = None
323
328
  model_config = ConfigDict(from_attributes=True, use_enum_values=True)
324
329
 
325
330
 
@@ -82,6 +82,7 @@ class BaseConnector(Generic[DB_CONNECTOR_TYPE], ABC):
82
82
  privacy_request: PrivacyRequest,
83
83
  request_task: RequestTask,
84
84
  rows: List[Row],
85
+ input_data: Optional[Dict[str, List[Any]]] = None,
85
86
  ) -> int:
86
87
  """Execute a masking request. Return the number of rows that have been updated
87
88
 
@@ -1,13 +1,8 @@
1
- from typing import List, Optional
1
+ from typing import Any, Dict, List, Optional
2
2
 
3
3
  from loguru import logger
4
4
  from sqlalchemy import text
5
- from sqlalchemy.engine import ( # type: ignore
6
- Connection,
7
- Engine,
8
- LegacyCursorResult,
9
- create_engine,
10
- )
5
+ from sqlalchemy.engine import Connection, Engine, create_engine # type: ignore
11
6
  from sqlalchemy.orm import Session
12
7
  from sqlalchemy.sql import Executable # type: ignore
13
8
  from sqlalchemy.sql.elements import TextClause
@@ -17,6 +12,7 @@ from fides.api.graph.execution import ExecutionNode
17
12
  from fides.api.models.connectionconfig import ConnectionTestStatus
18
13
  from fides.api.models.policy import Policy
19
14
  from fides.api.models.privacy_request import PrivacyRequest, RequestTask
15
+ from fides.api.schemas.application_config import SqlDryRunMode
20
16
  from fides.api.schemas.connection_configuration.connection_secrets_bigquery import (
21
17
  BigQuerySchema,
22
18
  )
@@ -99,6 +95,16 @@ class BigQueryConnector(SQLConnector):
99
95
  logger.info(
100
96
  f"Executing {len(partition_clauses)} partition queries for node '{query_config.node.address}' in DSR execution"
101
97
  )
98
+
99
+ if self.should_dry_run(SqlDryRunMode.access):
100
+ for partition_clause in partition_clauses:
101
+ existing_bind_params = stmt.compile().params
102
+ partitioned_stmt = text(
103
+ f"{stmt} AND ({text(partition_clause)})"
104
+ ).params(existing_bind_params)
105
+ logger.warning(f"SQL DRY RUN - Would execute SQL: {partitioned_stmt}")
106
+ return []
107
+
102
108
  rows = []
103
109
  for partition_clause in partition_clauses:
104
110
  logger.debug(
@@ -135,6 +141,39 @@ class BigQueryConnector(SQLConnector):
135
141
  logger.exception(f"Error testing connection to remote BigQuery {str(e)}")
136
142
  raise ConnectionException(f"Connection error: {e}")
137
143
 
144
+ def _execute_statements_with_sql_dry_run(
145
+ self,
146
+ statements: List[Executable],
147
+ sql_dry_run_enabled: bool,
148
+ client: Engine,
149
+ ) -> int:
150
+ """
151
+ Execute SQL statements with sql_dry_run support.
152
+
153
+ Args:
154
+ statements: List of SQL statements to execute
155
+ sql_dry_run_enabled: Whether sql_dry_run mode is enabled
156
+ client: Database engine
157
+
158
+ Returns:
159
+ int: Number of affected rows (0 in sql_dry_run mode)
160
+ """
161
+ if not statements:
162
+ return 0
163
+
164
+ if sql_dry_run_enabled:
165
+ for stmt in statements:
166
+ logger.warning(f"SQL DRY RUN - Would execute SQL: {stmt}")
167
+ return 0
168
+
169
+ row_count = 0
170
+ with client.connect() as connection:
171
+ for stmt in statements:
172
+ results = connection.execute(stmt)
173
+ logger.debug(f"Affected {results.rowcount} rows")
174
+ row_count += results.rowcount
175
+ return row_count
176
+
138
177
  def mask_data(
139
178
  self,
140
179
  node: ExecutionNode,
@@ -142,22 +181,31 @@ class BigQueryConnector(SQLConnector):
142
181
  privacy_request: PrivacyRequest,
143
182
  request_task: RequestTask,
144
183
  rows: List[Row],
184
+ input_data: Optional[Dict[str, List[Any]]] = None,
145
185
  ) -> int:
146
186
  """Execute a masking request. Returns the number of records updated or deleted"""
187
+
147
188
  query_config = self.query_config(node)
148
189
  update_or_delete_ct = 0
149
190
  client = self.client()
150
- for row in rows:
151
- update_or_delete_stmts: List[Executable] = (
152
- query_config.generate_masking_stmt(
153
- node, row, policy, privacy_request, client
154
- )
191
+
192
+ if query_config.uses_delete_masking_strategy():
193
+ delete_stmts = query_config.generate_delete(client, input_data or {})
194
+ logger.debug(f"Generated {len(delete_stmts)} DELETE statements")
195
+ update_or_delete_ct += self._execute_statements_with_sql_dry_run(
196
+ delete_stmts, self.should_dry_run(SqlDryRunMode.erasure), client
155
197
  )
156
- if update_or_delete_stmts:
157
- with client.connect() as connection:
158
- for update_or_delete_stmt in update_or_delete_stmts:
159
- results: LegacyCursorResult = connection.execute(
160
- update_or_delete_stmt
161
- )
162
- update_or_delete_ct = update_or_delete_ct + results.rowcount
198
+ else:
199
+ for row in rows:
200
+ update_or_delete_stmts: List[Executable] = query_config.generate_update(
201
+ row, policy, privacy_request, client
202
+ )
203
+ logger.debug(
204
+ f"Generated {len(update_or_delete_stmts)} UPDATE statements"
205
+ )
206
+ update_or_delete_ct += self._execute_statements_with_sql_dry_run(
207
+ update_or_delete_stmts,
208
+ self.should_dry_run(SqlDryRunMode.erasure),
209
+ client,
210
+ )
163
211
  return update_or_delete_ct
@@ -140,8 +140,9 @@ class DynamoDBConnector(BaseConnector[Any]): # type: ignore
140
140
  privacy_request: PrivacyRequest,
141
141
  request_task: RequestTask,
142
142
  rows: List[Row],
143
+ input_data: Optional[Dict[str, List[Any]]] = None,
143
144
  ) -> int:
144
- """Execute a masking requestfor DynamoDB"""
145
+ """Execute a masking request for DynamoDB"""
145
146
 
146
147
  query_config = self.query_config(node)
147
148
  collection_name = node.address.collection
@@ -142,6 +142,7 @@ class FidesConnector(BaseConnector[FidesClient]):
142
142
  privacy_request: PrivacyRequest,
143
143
  request_task: RequestTask,
144
144
  rows: List[Row],
145
+ input_data: Optional[Dict[str, List[Any]]] = None,
145
146
  ) -> int:
146
147
  """Execute an erasure request on remote fides"""
147
148
  identity_data = {
@@ -90,6 +90,7 @@ class HTTPSConnector(BaseConnector[None]):
90
90
  privacy_request: PrivacyRequest,
91
91
  request_task: RequestTask,
92
92
  rows: List[Row],
93
+ input_data: Optional[Dict[str, List[Any]]] = None,
93
94
  ) -> int:
94
95
  """Currently not supported as webhooks are not called at the collection level"""
95
96
  raise NotImplementedError(
@@ -80,6 +80,7 @@ class ManualTaskConnector(BaseConnector):
80
80
  privacy_request: PrivacyRequest,
81
81
  request_task: RequestTask,
82
82
  rows: List[Row],
83
+ input_data: Optional[Dict[str, List[Any]]] = None,
83
84
  ) -> int:
84
85
  """
85
86
  Manual tasks don't support erasure operations.
@@ -1,4 +1,4 @@
1
- from typing import Any, Dict, List
1
+ from typing import Any, Dict, List, Optional
2
2
 
3
3
  from fides.api.graph.execution import ExecutionNode
4
4
  from fides.api.models.connectionconfig import ConnectionConfig, ConnectionTestStatus
@@ -53,6 +53,7 @@ class ManualWebhookConnector(BaseConnector[None]):
53
53
  privacy_request: PrivacyRequest,
54
54
  request_task: RequestTask,
55
55
  rows: List[Row],
56
+ input_data: Optional[List[List[Row]]] = None,
56
57
  ) -> None:
57
58
  """
58
59
  Not applicable for a manual webhook. Manual webhooks are not called as part of the traversal.
@@ -126,6 +126,7 @@ class MongoDBConnector(BaseConnector[MongoClient]):
126
126
  privacy_request: PrivacyRequest,
127
127
  request_task: RequestTask,
128
128
  rows: List[Row],
129
+ input_data: Optional[Dict[str, List[Any]]] = None,
129
130
  ) -> int:
130
131
  """Execute a masking request"""
131
132
  query_config = self.query_config(node)
@@ -82,6 +82,7 @@ class OktaConnector(BaseConnector):
82
82
  privacy_request: PrivacyRequest,
83
83
  request_task: RequestTask,
84
84
  rows: List[Row],
85
+ input_data: Optional[Dict[str, List[Any]]] = None,
85
86
  ) -> int:
86
87
  """DSR execution not supported for Okta connector"""
87
88
  return 0