ethyca-fides 2.65.1b1__py2.py3-none-any.whl → 2.65.1b2__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 (237) hide show
  1. {ethyca_fides-2.65.1b1.dist-info → ethyca_fides-2.65.1b2.dist-info}/METADATA +1 -1
  2. {ethyca_fides-2.65.1b1.dist-info → ethyca_fides-2.65.1b2.dist-info}/RECORD +218 -215
  3. fides/_version.py +3 -3
  4. fides/api/alembic/migrations/versions/3b0f4905378c_change_asset_with_consent_to_asset_.py +47 -0
  5. fides/api/alembic/migrations/versions/9e3dab26f75f_add_test_website_to_connectiontype.py +51 -0
  6. fides/api/alembic/migrations/versions/d45dec7e541d_add_consent_indexes_to_stagedresource.py +64 -0
  7. fides/api/api/v1/endpoints/privacy_request_endpoints.py +24 -1
  8. fides/api/migrations/post_upgrade_index_creation.py +12 -0
  9. fides/api/models/asset.py +19 -2
  10. fides/api/models/connectionconfig.py +4 -0
  11. fides/api/models/detection_discovery/core.py +17 -0
  12. fides/api/oauth/roles.py +2 -0
  13. fides/api/schemas/api.py +6 -0
  14. fides/api/schemas/connection_configuration/__init__.py +1 -0
  15. fides/api/service/connectors/__init__.py +1 -0
  16. fides/api/service/connectors/base_email_connector.py +1 -1
  17. fides/api/service/connectors/base_erasure_email_connector.py +39 -2
  18. fides/api/service/connectors/consent_email_connector.py +1 -1
  19. fides/api/service/connectors/dynamic_erasure_email_connector.py +14 -48
  20. fides/api/service/connectors/erasure_email_connector.py +14 -8
  21. fides/api/service/privacy_request/email_batch_service.py +68 -52
  22. fides/api/tasks/scheduled/scheduler.py +5 -0
  23. fides/api/util/connection_type.py +1 -0
  24. fides/api/util/lock.py +3 -0
  25. fides/common/api/scope_registry.py +4 -0
  26. fides/common/api/v1/urn_registry.py +3 -0
  27. fides/config/execution_settings.py +8 -0
  28. fides/ui-build/static/admin/404.html +1 -1
  29. fides/ui-build/static/admin/_next/static/FyEBF3yHHs8bgX7Ko0ZD_/_buildManifest.js +1 -0
  30. fides/ui-build/static/admin/_next/static/chunks/{1817-f2f34b8bd569ae1d.js → 1817-e2c599fb2c47dbc4.js} +1 -1
  31. fides/ui-build/static/admin/_next/static/chunks/{2921-c19da1016b81bda3.js → 2921-93228aa02364bb48.js} +1 -1
  32. fides/ui-build/static/admin/_next/static/chunks/3450-ebcffdd4fb437a2e.js +1 -0
  33. fides/ui-build/static/admin/_next/static/chunks/{3855-44e1171660633b6f.js → 3855-a0783ba28c644d09.js} +1 -1
  34. fides/ui-build/static/admin/_next/static/chunks/{3872-a7ee651751f5e145.js → 3872-18e5da8bda649ddb.js} +1 -1
  35. fides/ui-build/static/admin/_next/static/chunks/{3923-5a82816119f8f907.js → 3923-536e8bbbea5b7328.js} +1 -1
  36. fides/ui-build/static/admin/_next/static/chunks/{3988-046b3a2866b5cb99.js → 3988-4b0f160b0969dbd2.js} +1 -1
  37. fides/ui-build/static/admin/_next/static/chunks/{401-7fa53f1e774e02fb.js → 401-002f393dae03f8f4.js} +1 -1
  38. fides/ui-build/static/admin/_next/static/chunks/{409-e80a4e415c04dd92.js → 409-6b1b506d59a0399a.js} +1 -1
  39. fides/ui-build/static/admin/_next/static/chunks/4121-23ac086c1aa6a43a.js +1 -0
  40. fides/ui-build/static/admin/_next/static/chunks/{4230-864eac33691cd299.js → 4230-c4c596fb5534e1b1.js} +1 -1
  41. fides/ui-build/static/admin/_next/static/chunks/431-24380873201c3e1b.js +1 -0
  42. fides/ui-build/static/admin/_next/static/chunks/4608-0cd97892fd0b0e41.js +1 -0
  43. fides/ui-build/static/admin/_next/static/chunks/5309-c8b5165efcc5469f.js +1 -0
  44. fides/ui-build/static/admin/_next/static/chunks/{5574-48d7c9a526a3a0fe.js → 5574-1fad13b944f0c4fc.js} +1 -1
  45. fides/ui-build/static/admin/_next/static/chunks/{6084-4a1964e1b20c9eee.js → 6084-5bfa390a4c8fad43.js} +1 -1
  46. fides/ui-build/static/admin/_next/static/chunks/{6662-94dbe989cbe548d9.js → 6662-79eee0bf18775b40.js} +1 -1
  47. fides/ui-build/static/admin/_next/static/chunks/6780-8b5772a3a2ef1ca6.js +1 -0
  48. fides/ui-build/static/admin/_next/static/chunks/{6853-19268388843a58f5.js → 6853-7a089a9fad286bb8.js} +1 -1
  49. fides/ui-build/static/admin/_next/static/chunks/{6882-f807b643776c8d47.js → 6882-5a251351689ea74b.js} +1 -1
  50. fides/ui-build/static/admin/_next/static/chunks/6954-3a7b166c8f3b66b4.js +1 -0
  51. fides/ui-build/static/admin/_next/static/chunks/{7476-7fc24f19a2cc563a.js → 7476-d7071697bc665a4f.js} +1 -1
  52. fides/ui-build/static/admin/_next/static/chunks/{7630-e0e04e495732ae8f.js → 7630-731324d74b20b80e.js} +1 -1
  53. fides/ui-build/static/admin/_next/static/chunks/{787-0c18bf9acef937de.js → 787-cb0154eaf6114c7e.js} +1 -1
  54. fides/ui-build/static/admin/_next/static/chunks/{79-d4c8900a83eb83bc.js → 79-f08e91084d10d6dc.js} +1 -1
  55. fides/ui-build/static/admin/_next/static/chunks/{796-a98f370ec9b5cbf9.js → 796-e33122908c5e28ce.js} +1 -1
  56. fides/ui-build/static/admin/_next/static/chunks/9046-d4c806aa81ab0bad.js +1 -0
  57. fides/ui-build/static/admin/_next/static/chunks/{9226-a5904e64ab72cb18.js → 9226-f4e70e6f9619e9a9.js} +1 -1
  58. fides/ui-build/static/admin/_next/static/chunks/{9392.bb5a989efef5b329.js → 9392.f4520f66206d347d.js} +1 -1
  59. fides/ui-build/static/admin/_next/static/chunks/{9676.549c72c3eb3df912.js → 9676.7fbcb6b554cda098.js} +1 -1
  60. fides/ui-build/static/admin/_next/static/chunks/{9826-7b769d4863df242a.js → 9826-065b7cd0784d6912.js} +1 -1
  61. fides/ui-build/static/admin/_next/static/chunks/{9951-27d79500acfefdd2.js → 9951-5e744e8addb6e090.js} +1 -1
  62. fides/ui-build/static/admin/_next/static/chunks/pages/{404-ac335065bc49f818.js → 404-beb4bf835acb4386.js} +1 -1
  63. fides/ui-build/static/admin/_next/static/chunks/pages/{_app-3e486cab9a918260.js → _app-ae72c7442ecd3e50.js} +8 -8
  64. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/manual-12073578f764815e.js +1 -0
  65. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{multiple-a2ae50c2f0e7608e.js → multiple-943479665698c6d2.js} +1 -1
  66. fides/ui-build/static/admin/_next/static/chunks/pages/{add-systems-4f20f18ec01fd15a.js → add-systems-e5ef5be6566f9432.js} +1 -1
  67. fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure/{add-vendors-4957c0b6fa498f6e.js → add-vendors-1bde4adc6d2a6dfa.js} +1 -1
  68. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{configure-3ede98dedea9f621.js → configure-e72c1feeb24bdb73.js} +1 -1
  69. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{[id]-f285b2dca83711ba.js → [id]-cc858383bb1bbd36.js} +1 -1
  70. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-experience-efa0f3e3991dc139.js → privacy-experience-5f2d060952814353.js} +1 -1
  71. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{[id]-21c96b42424c33bc.js → [id]-bfca5064b33116b9.js} +1 -1
  72. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{new-e494f14ce371390c.js → new-e4a9393b7572e591.js} +1 -1
  73. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-notices-25cb30b4585622d6.js → privacy-notices-232e9ef135b838cf.js} +1 -1
  74. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{properties-78ba4553dd12d0d3.js → properties-a05600d9e3e8735e.js} +1 -1
  75. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{reporting-b65b5ab73dfcb801.js → reporting-5fcacc8e4baf3d03.js} +1 -1
  76. fides/ui-build/static/admin/_next/static/chunks/pages/{consent-87c06e0daf2b2e87.js → consent-bd0fbeabe84d3c8f.js} +1 -1
  77. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/{[projectUrn]-c956a3faed9f922c.js → [projectUrn]-00bbbfb19c15c48d.js} +1 -1
  78. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{projects-691e19bdd29b8c3b.js → projects-be252cac70aa63dd.js} +1 -1
  79. fides/ui-build/static/admin/_next/static/chunks/pages/{data-catalog-b1616ecfd86a2e2e.js → data-catalog-29cde3b7d27b22cf.js} +1 -1
  80. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-3ae1ae3844a6e03a.js +1 -0
  81. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]-e8dc8320e826e91c.js +1 -0
  82. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{action-center-a694e71d11bed653.js → action-center-22fe027966edb092.js} +1 -1
  83. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{activity-312edbab3c17f26a.js → activity-f79ec067d906e67f.js} +1 -1
  84. fides/ui-build/static/admin/_next/static/chunks/pages/{datamap-e8bfa1a3a8b84b6d.js → datamap-639ac9cf51750635.js} +1 -1
  85. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/{[...subfieldNames]-f976632b92911072.js → [...subfieldNames]-d69aff79e77c5464.js} +1 -1
  86. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/{[collectionName]-9ffa34d7ee7b2872.js → [collectionName]-9df954c65a9fe023.js} +1 -1
  87. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/{[datasetId]-6e65dcdd692b4625.js → [datasetId]-0e90202b2db3797c.js} +1 -1
  88. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/{new-423f08db5d9adc9a.js → new-403dc361bffe644d.js} +1 -1
  89. fides/ui-build/static/admin/_next/static/chunks/pages/{dataset-2bd2b941ad8f87b1.js → dataset-52506e743c73fc7d.js} +1 -1
  90. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/[id]-7d492050fc33a57a.js +1 -0
  91. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/new-6f68e65f01beb8af.js +1 -0
  92. fides/ui-build/static/admin/_next/static/chunks/pages/{datastore-connection-6b02666ce735e092.js → datastore-connection-36eeca2fe22be33a.js} +1 -1
  93. fides/ui-build/static/admin/_next/static/chunks/pages/{index-99ad22eddbb6b7f2.js → index-e92db8bb8c719abc.js} +1 -1
  94. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-c245f0b0fd7810c0.js +1 -0
  95. fides/ui-build/static/admin/_next/static/chunks/pages/integrations-ea492832424a9619.js +1 -0
  96. fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{[id]-8970d29f1710f486.js → [id]-78606d74f82f5edc.js} +1 -1
  97. fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{add-template-db905b79b189989c.js → add-template-9dff500113f0710f.js} +1 -1
  98. fides/ui-build/static/admin/_next/static/chunks/pages/{messaging-10084105bae43a19.js → messaging-c17efc84c54e4fdb.js} +1 -1
  99. fides/ui-build/static/admin/_next/static/chunks/pages/poc/{ant-components-cf7c0b3782c0c7a6.js → ant-components-74348d35e92a2a3c.js} +1 -1
  100. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{AntForm-8cf5c6bb7f4595eb.js → AntForm-ac613f99cd57d7b3.js} +1 -1
  101. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikAntFormItem-01904c9c8521ef1c.js → FormikAntFormItem-44605674baae28e2.js} +1 -1
  102. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikControlled-ed8c23307b2b6868.js → FormikControlled-86761304f1da7172.js} +1 -1
  103. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikField-3ec8e1811906a1d2.js → FormikField-fadf4e866aa8ea22.js} +1 -1
  104. fides/ui-build/static/admin/_next/static/chunks/pages/poc/{forms-18fc8b3a8ccfc80b.js → forms-be9bc54243141257.js} +1 -1
  105. fides/ui-build/static/admin/_next/static/chunks/pages/poc/{table-migration-372166dc1d6268ea.js → table-migration-69a9e346e32fde53.js} +1 -1
  106. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/{[id]-104f33c424613732.js → [id]-61e32a7b8ef6569c.js} +1 -1
  107. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/{messaging-a29479bc35b00f45.js → messaging-1f57e4d5715dd5cf.js} +1 -1
  108. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/{storage-10e2886bc4d4f62b.js → storage-378db5585b89ab5e.js} +1 -1
  109. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/{configure-340150cac5bf8e4a.js → configure-6935d3c1655ecbbe.js} +1 -1
  110. fides/ui-build/static/admin/_next/static/chunks/pages/{privacy-requests-b1772281866cb827.js → privacy-requests-d3299d80983c3587.js} +1 -1
  111. fides/ui-build/static/admin/_next/static/chunks/pages/properties/{[id]-d9cdc82249593440.js → [id]-3a7b2edeb6f6c7a2.js} +1 -1
  112. fides/ui-build/static/admin/_next/static/chunks/pages/properties/{add-property-d2e0236ab65b1fb9.js → add-property-971657cbd5e5490f.js} +1 -1
  113. fides/ui-build/static/admin/_next/static/chunks/pages/{properties-156bd0e36831ed04.js → properties-be3668cbd03e086e.js} +1 -1
  114. fides/ui-build/static/admin/_next/static/chunks/pages/reporting/{datamap-49e5607055db1bee.js → datamap-dc3afcf514d7219a.js} +1 -1
  115. fides/ui-build/static/admin/_next/static/chunks/pages/settings/about/{alpha-68697c49b290ba50.js → alpha-fb0c7974234d93ee.js} +1 -1
  116. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{about-a45a5b9f78c64e27.js → about-a91bf9cf821bcdcb.js} +1 -1
  117. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent/[configuration_id]/{[purpose_id]-c54d90dd4ac04de3.js → [purpose_id]-aaa2d02b9be2acb1.js} +1 -1
  118. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{consent-2ecf179f6587e3b3.js → consent-bed42ecfab4896af.js} +1 -1
  119. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{custom-fields-80bf043deb37a20c.js → custom-fields-82882bc16052ae5b.js} +1 -1
  120. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domain-records-c2ef327dc49618e9.js → domain-records-9455a95901d7d223.js} +1 -1
  121. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domains-bdc7ee59802c2e4a.js → domains-57fd9412882c4ab2.js} +1 -1
  122. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{email-templates-6af619d1d57bb99c.js → email-templates-63a5da14576722a4.js} +1 -1
  123. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{locations-09cb08245844c601.js → locations-068724e9c574974d.js} +1 -1
  124. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{organization-d9e7feee568f6e35.js → organization-f556688c5fb35f41.js} +1 -1
  125. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{regulations-7cfbb9149f96961a.js → regulations-3ddf2001f4605949.js} +1 -1
  126. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/{test-datasets-9f5912cb2f471fdf.js → test-datasets-7ce5dbabf7f1026b.js} +1 -1
  127. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]-ed809e0961891c0c.js +1 -0
  128. fides/ui-build/static/admin/_next/static/chunks/pages/{systems-5332864c5e8595dc.js → systems-b5f68d37abaa8844.js} +1 -1
  129. fides/ui-build/static/admin/_next/static/chunks/pages/{taxonomy-80f4ab8b7b6e7f5e.js → taxonomy-103618fab50dfd0d.js} +1 -1
  130. fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/{[id]-e607e07bd1ef2da0.js → [id]-564f87da93e398d0.js} +1 -1
  131. fides/ui-build/static/admin/_next/static/chunks/pages/{user-management-d539f1c4e6adf73a.js → user-management-f552cb870f8a6a17.js} +1 -1
  132. fides/ui-build/static/admin/_next/static/chunks/webpack-c97e8d65bd9739ff.js +1 -0
  133. fides/ui-build/static/admin/_next/static/css/0ba8f1215e9015ff.css +1 -0
  134. fides/ui-build/static/admin/add-systems/manual.html +1 -1
  135. fides/ui-build/static/admin/add-systems/multiple.html +1 -1
  136. fides/ui-build/static/admin/add-systems.html +1 -1
  137. fides/ui-build/static/admin/consent/configure/add-vendors.html +1 -1
  138. fides/ui-build/static/admin/consent/configure.html +1 -1
  139. fides/ui-build/static/admin/consent/privacy-experience/[id].html +1 -1
  140. fides/ui-build/static/admin/consent/privacy-experience/new.html +1 -1
  141. fides/ui-build/static/admin/consent/privacy-experience.html +1 -1
  142. fides/ui-build/static/admin/consent/privacy-notices/[id].html +1 -1
  143. fides/ui-build/static/admin/consent/privacy-notices/new.html +1 -1
  144. fides/ui-build/static/admin/consent/privacy-notices.html +1 -1
  145. fides/ui-build/static/admin/consent/properties.html +1 -1
  146. fides/ui-build/static/admin/consent/reporting.html +1 -1
  147. fides/ui-build/static/admin/consent.html +1 -1
  148. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn].html +1 -1
  149. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn].html +1 -1
  150. fides/ui-build/static/admin/data-catalog/[systemId]/projects.html +1 -1
  151. fides/ui-build/static/admin/data-catalog/[systemId]/resources/[resourceUrn].html +1 -1
  152. fides/ui-build/static/admin/data-catalog/[systemId]/resources.html +1 -1
  153. fides/ui-build/static/admin/data-catalog.html +1 -1
  154. fides/ui-build/static/admin/data-discovery/action-center/[monitorId]/[systemId].html +1 -1
  155. fides/ui-build/static/admin/data-discovery/action-center/[monitorId].html +1 -1
  156. fides/ui-build/static/admin/data-discovery/action-center.html +1 -1
  157. fides/ui-build/static/admin/data-discovery/activity.html +1 -1
  158. fides/ui-build/static/admin/data-discovery/detection/[resourceUrn].html +1 -1
  159. fides/ui-build/static/admin/data-discovery/detection.html +1 -1
  160. fides/ui-build/static/admin/data-discovery/discovery/[resourceUrn].html +1 -1
  161. fides/ui-build/static/admin/data-discovery/discovery.html +1 -1
  162. fides/ui-build/static/admin/datamap.html +1 -1
  163. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName]/[...subfieldNames].html +1 -1
  164. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName].html +1 -1
  165. fides/ui-build/static/admin/dataset/[datasetId].html +1 -1
  166. fides/ui-build/static/admin/dataset/new.html +1 -1
  167. fides/ui-build/static/admin/dataset.html +1 -1
  168. fides/ui-build/static/admin/datastore-connection/[id].html +1 -1
  169. fides/ui-build/static/admin/datastore-connection/new.html +1 -1
  170. fides/ui-build/static/admin/datastore-connection.html +1 -1
  171. fides/ui-build/static/admin/index.html +1 -1
  172. fides/ui-build/static/admin/integrations/[id].html +1 -1
  173. fides/ui-build/static/admin/integrations.html +1 -1
  174. fides/ui-build/static/admin/login/[provider].html +1 -1
  175. fides/ui-build/static/admin/login.html +1 -1
  176. fides/ui-build/static/admin/messaging/[id].html +1 -1
  177. fides/ui-build/static/admin/messaging/add-template.html +1 -1
  178. fides/ui-build/static/admin/messaging.html +1 -1
  179. fides/ui-build/static/admin/poc/ant-components.html +1 -1
  180. fides/ui-build/static/admin/poc/form-experiments/AntForm.html +1 -1
  181. fides/ui-build/static/admin/poc/form-experiments/FormikAntFormItem.html +1 -1
  182. fides/ui-build/static/admin/poc/form-experiments/FormikControlled.html +1 -1
  183. fides/ui-build/static/admin/poc/form-experiments/FormikField.html +1 -1
  184. fides/ui-build/static/admin/poc/form-experiments/FormikSpreadField.html +1 -1
  185. fides/ui-build/static/admin/poc/forms.html +1 -1
  186. fides/ui-build/static/admin/poc/table-migration.html +1 -1
  187. fides/ui-build/static/admin/privacy-requests/[id].html +1 -1
  188. fides/ui-build/static/admin/privacy-requests/configure/messaging.html +1 -1
  189. fides/ui-build/static/admin/privacy-requests/configure/storage.html +1 -1
  190. fides/ui-build/static/admin/privacy-requests/configure.html +1 -1
  191. fides/ui-build/static/admin/privacy-requests.html +1 -1
  192. fides/ui-build/static/admin/properties/[id].html +1 -1
  193. fides/ui-build/static/admin/properties/add-property.html +1 -1
  194. fides/ui-build/static/admin/properties.html +1 -1
  195. fides/ui-build/static/admin/reporting/datamap.html +1 -1
  196. fides/ui-build/static/admin/settings/about/alpha.html +1 -1
  197. fides/ui-build/static/admin/settings/about.html +1 -1
  198. fides/ui-build/static/admin/settings/consent/[configuration_id]/[purpose_id].html +1 -1
  199. fides/ui-build/static/admin/settings/consent.html +1 -1
  200. fides/ui-build/static/admin/settings/custom-fields.html +1 -1
  201. fides/ui-build/static/admin/settings/domain-records.html +1 -1
  202. fides/ui-build/static/admin/settings/domains.html +1 -1
  203. fides/ui-build/static/admin/settings/email-templates.html +1 -1
  204. fides/ui-build/static/admin/settings/locations.html +1 -1
  205. fides/ui-build/static/admin/settings/organization.html +1 -1
  206. fides/ui-build/static/admin/settings/regulations.html +1 -1
  207. fides/ui-build/static/admin/systems/configure/[id]/test-datasets.html +1 -1
  208. fides/ui-build/static/admin/systems/configure/[id].html +1 -1
  209. fides/ui-build/static/admin/systems.html +1 -1
  210. fides/ui-build/static/admin/taxonomy.html +1 -1
  211. fides/ui-build/static/admin/user-management/new.html +1 -1
  212. fides/ui-build/static/admin/user-management/profile/[id].html +1 -1
  213. fides/ui-build/static/admin/user-management.html +1 -1
  214. fides/ui-build/static/admin/_next/static/chunks/1040-94f81c731c29246d.js +0 -1
  215. fides/ui-build/static/admin/_next/static/chunks/3450-84ea89e7a0f95470.js +0 -1
  216. fides/ui-build/static/admin/_next/static/chunks/4121-536e7e853d0833c0.js +0 -1
  217. fides/ui-build/static/admin/_next/static/chunks/431-458946a2cae21b5d.js +0 -1
  218. fides/ui-build/static/admin/_next/static/chunks/5309-018fe2068151d699.js +0 -1
  219. fides/ui-build/static/admin/_next/static/chunks/6954-ec0697d355730f74.js +0 -1
  220. fides/ui-build/static/admin/_next/static/chunks/9046-b3dccae317a7bae5.js +0 -1
  221. fides/ui-build/static/admin/_next/static/chunks/9767-9afc910b855d913a.js +0 -1
  222. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/manual-3964f3039ce3f18c.js +0 -1
  223. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-052028439e802c76.js +0 -1
  224. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]-99d3a2197ab8a9b0.js +0 -1
  225. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/[id]-1b7bfb005fd8e4e1.js +0 -1
  226. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/new-b737165f7752f039.js +0 -1
  227. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-97f9e9b2822d2576.js +0 -1
  228. fides/ui-build/static/admin/_next/static/chunks/pages/integrations-4ce156e73fe3608f.js +0 -1
  229. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]-0252e5f648c5e3f8.js +0 -1
  230. fides/ui-build/static/admin/_next/static/chunks/webpack-8fc1c717e1c0f7ae.js +0 -1
  231. fides/ui-build/static/admin/_next/static/css/5f8af79f94072e0f.css +0 -1
  232. fides/ui-build/static/admin/_next/static/nlHJ2XI_Rq9Lg0rOXnZXC/_buildManifest.js +0 -1
  233. {ethyca_fides-2.65.1b1.dist-info → ethyca_fides-2.65.1b2.dist-info}/WHEEL +0 -0
  234. {ethyca_fides-2.65.1b1.dist-info → ethyca_fides-2.65.1b2.dist-info}/entry_points.txt +0 -0
  235. {ethyca_fides-2.65.1b1.dist-info → ethyca_fides-2.65.1b2.dist-info}/licenses/LICENSE +0 -0
  236. {ethyca_fides-2.65.1b1.dist-info → ethyca_fides-2.65.1b2.dist-info}/top_level.txt +0 -0
  237. /fides/ui-build/static/admin/_next/static/{nlHJ2XI_Rq9Lg0rOXnZXC → FyEBF3yHHs8bgX7Ko0ZD_}/_ssgManifest.js +0 -0
fides/_version.py CHANGED
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2025-07-09T11:43:42-0600",
11
+ "date": "2025-07-10T11:18:51-0300",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "9579495c14ebf76d7decc8e13069a89db5b4e721",
15
- "version": "2.65.1b1"
14
+ "full-revisionid": "a74b823bafe8947c6859f0ace17b7b9f4973ff4b",
15
+ "version": "2.65.1b2"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -0,0 +1,47 @@
1
+ """Change Asset.with_consent to Asset.consent_status
2
+
3
+ Revision ID: 3b0f4905378c
4
+ Revises: 641f6bcd424f
5
+ Create Date: 2025-07-01 15:17:32.542511
6
+
7
+ """
8
+
9
+ import sqlalchemy as sa
10
+ from alembic import op
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = "3b0f4905378c"
14
+ down_revision = "641f6bcd424f"
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade():
20
+ # ### commands auto generated by Alembic - please adjust! ###
21
+ op.execute(
22
+ "create type consentstatus as enum ('with_consent', 'without_consent', 'exempt', 'unknown')"
23
+ )
24
+ op.add_column(
25
+ "asset",
26
+ sa.Column(
27
+ "consent_status",
28
+ sa.Enum(
29
+ name="consentstatus",
30
+ ),
31
+ server_default="unknown",
32
+ nullable=False,
33
+ ),
34
+ )
35
+ op.drop_column("asset", "with_consent")
36
+ # ### end Alembic commands ###
37
+
38
+
39
+ def downgrade():
40
+ # ### commands auto generated by Alembic - please adjust! ###
41
+ op.add_column(
42
+ "asset",
43
+ sa.Column("with_consent", sa.BOOLEAN(), autoincrement=False, nullable=False),
44
+ )
45
+ op.drop_column("asset", "consent_status")
46
+ op.execute("drop type if exists consentstatus")
47
+ # ### end Alembic commands ###
@@ -0,0 +1,51 @@
1
+ """Add test_website to ConnectionType
2
+
3
+ Revision ID: 9e3dab26f75f
4
+ Revises: d45dec7e541d
5
+ Create Date: 2025-07-02 14:11:53.403439
6
+
7
+ """
8
+
9
+ import sqlalchemy as sa
10
+ from alembic import op
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = "9e3dab26f75f"
14
+ down_revision = "d45dec7e541d"
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade():
20
+ # Add test_website to ConnectionType enum
21
+ op.execute("alter type connectiontype rename to connectiontype_old")
22
+ op.execute(
23
+ "create type connectiontype as enum('attentive_email', 'bigquery', 'datahub', 'dynamodb', 'fides', 'generic_consent_email', 'generic_erasure_email', 'dynamic_erasure_email', 'google_cloud_sql_mysql', 'google_cloud_sql_postgres', 'https', 'manual', 'manual_webhook', 'manual_task', 'mariadb', 'mongodb', 'mssql', 'mysql', 'okta', 'postgres', 'rds_mysql', 'rds_postgres', 'redshift', 's3', 'saas', 'scylla', 'snowflake', 'sovrn', 'test_website', 'timescale', 'website')"
24
+ )
25
+ op.execute(
26
+ (
27
+ "alter table connectionconfig alter column connection_type type connectiontype using "
28
+ "connection_type::text::connectiontype"
29
+ )
30
+ )
31
+ op.execute("drop type connectiontype_old")
32
+
33
+
34
+ def downgrade():
35
+ # First remove the ConnectionConfigs with connection_type = 'test_website'
36
+ op.execute("delete from connectionconfig where connection_type in ('test_website')")
37
+ # Then remove 'test_website' from ConnectionType enum by renaming old enum
38
+ op.execute("alter type connectiontype rename to connectiontype_old")
39
+ # Create a new enum without 'test_website'
40
+ op.execute(
41
+ "create type connectiontype as enum('attentive_email', 'bigquery', 'datahub', 'dynamodb', 'fides', 'generic_consent_email', 'generic_erasure_email', 'dynamic_erasure_email', 'google_cloud_sql_mysql', 'google_cloud_sql_postgres', 'https', 'manual', 'manual_webhook', 'manual_task', 'mariadb', 'mongodb', 'mssql', 'mysql', 'okta', 'postgres', 'rds_mysql', 'rds_postgres', 'redshift', 's3', 'saas', 'scylla', 'snowflake', 'sovrn', 'timescale', 'website')"
42
+ )
43
+ # Alter the connectionconfig table to use the new enum
44
+ op.execute(
45
+ (
46
+ "alter table connectionconfig alter column connection_type type connectiontype using "
47
+ "connection_type::text::connectiontype"
48
+ )
49
+ )
50
+ # Drop the old enum
51
+ op.execute("drop type connectiontype_old")
@@ -0,0 +1,64 @@
1
+ """Add consent indexes to stagedresource
2
+
3
+ Revision ID: d45dec7e541d
4
+ Revises: 3b0f4905378c
5
+ Create Date: 2025-07-01 19:50:25.009417
6
+
7
+ """
8
+
9
+ import sqlalchemy as sa
10
+ from alembic import op
11
+ from loguru import logger
12
+
13
+ # revision identifiers, used by Alembic.
14
+ revision = "d45dec7e541d"
15
+ down_revision = "3b0f4905378c"
16
+ branch_labels = None
17
+ depends_on = None
18
+
19
+
20
+ def upgrade():
21
+ # ### commands auto generated by Alembic - please adjust! ###
22
+ connection = op.get_bind()
23
+
24
+ # Check stagedresource table size to decide if we should create indexes immediately
25
+ stagedresource_count = connection.execute(
26
+ sa.text("SELECT COUNT(*) FROM stagedresource")
27
+ ).scalar()
28
+
29
+ if stagedresource_count < 1000000:
30
+ # Create indexes normally for smaller tables
31
+ op.create_index(
32
+ "ix_stagedresource_monitor_config_resource_type_consent",
33
+ "stagedresource",
34
+ [
35
+ "monitor_config_id",
36
+ "resource_type",
37
+ sa.text("(meta->>'consent_aggregated')"),
38
+ ],
39
+ unique=False,
40
+ )
41
+ op.create_index(
42
+ "ix_stagedresource_system_vendor_consent",
43
+ "stagedresource",
44
+ ["system_id", "vendor_id", sa.text("(meta->>'consent_aggregated')")],
45
+ unique=False,
46
+ )
47
+ else:
48
+ logger.warning(
49
+ "The stagedresource table has more than 1 million rows, "
50
+ "skipping index creation. Indexes will be created during application startup "
51
+ "via post_upgrade_index_creation.py"
52
+ )
53
+ # ### end Alembic commands ###
54
+
55
+
56
+ def downgrade():
57
+ # ### commands auto generated by Alembic - please adjust! ###
58
+ # Drop indexes if they exist (they may not exist if they were deferred)
59
+ op.execute("DROP INDEX IF EXISTS ix_stagedresource_system_vendor_consent")
60
+ op.execute(
61
+ "DROP INDEX IF EXISTS ix_stagedresource_monitor_config_resource_type_consent"
62
+ )
63
+
64
+ # ### end Alembic commands ###
@@ -19,7 +19,7 @@ from typing import (
19
19
  )
20
20
 
21
21
  import sqlalchemy
22
- from fastapi import Body, Depends, HTTPException, Security
22
+ from fastapi import BackgroundTasks, Body, Depends, HTTPException, Security
23
23
  from fastapi.encoders import jsonable_encoder
24
24
  from fastapi.params import Query as FastAPIQuery
25
25
  from fastapi_pagination import Page, Params
@@ -82,6 +82,7 @@ from fides.api.oauth.utils import (
82
82
  verify_oauth_client,
83
83
  verify_request_task_callback,
84
84
  )
85
+ from fides.api.schemas.api import ResponseWithMessage
85
86
  from fides.api.schemas.dataset import CollectionAddressResponse, DryRunDatasetResponse
86
87
  from fides.api.schemas.external_https import PrivacyRequestResumeFormat
87
88
  from fides.api.schemas.policy import ActionType
@@ -110,6 +111,7 @@ from fides.api.schemas.privacy_request import (
110
111
  )
111
112
  from fides.api.service.deps import get_messaging_service, get_privacy_request_service
112
113
  from fides.api.service.messaging.message_dispatch_service import EMAIL_JOIN_STRING
114
+ from fides.api.service.privacy_request.email_batch_service import send_email_batch
113
115
  from fides.api.task.execute_request_tasks import log_task_queued, queue_request_task
114
116
  from fides.api.task.filter_results import filter_data_categories
115
117
  from fides.api.task.graph_task import EMPTY_REQUEST, EMPTY_REQUEST_TASK, collect_queries
@@ -125,6 +127,7 @@ from fides.common.api.scope_registry import (
125
127
  PRIVACY_REQUEST_CALLBACK_RESUME,
126
128
  PRIVACY_REQUEST_CREATE,
127
129
  PRIVACY_REQUEST_DELETE,
130
+ PRIVACY_REQUEST_EMAIL_INTEGRATIONS_SEND,
128
131
  PRIVACY_REQUEST_NOTIFICATIONS_CREATE_OR_UPDATE,
129
132
  PRIVACY_REQUEST_NOTIFICATIONS_READ,
130
133
  PRIVACY_REQUEST_READ,
@@ -138,6 +141,7 @@ from fides.common.api.v1.urn_registry import (
138
141
  PRIVACY_REQUEST_ACCESS_RESULTS,
139
142
  PRIVACY_REQUEST_APPROVE,
140
143
  PRIVACY_REQUEST_AUTHENTICATED,
144
+ PRIVACY_REQUEST_BATCH_EMAIL_SEND,
141
145
  PRIVACY_REQUEST_BULK_RETRY,
142
146
  PRIVACY_REQUEST_BULK_SOFT_DELETE,
143
147
  PRIVACY_REQUEST_DENY,
@@ -2277,3 +2281,22 @@ def get_test_privacy_request_logs(
2277
2281
  # Get logs from Redis
2278
2282
  cache = get_cache()
2279
2283
  return cache.get_decoded_list(f"log_{privacy_request_id}") or []
2284
+
2285
+
2286
+ @router.post(
2287
+ PRIVACY_REQUEST_BATCH_EMAIL_SEND,
2288
+ dependencies=[
2289
+ Security(verify_oauth_client, scopes=[PRIVACY_REQUEST_EMAIL_INTEGRATIONS_SEND])
2290
+ ],
2291
+ status_code=HTTP_200_OK,
2292
+ response_model=ResponseWithMessage,
2293
+ )
2294
+ def send_batch_email_integrations(
2295
+ background_tasks: BackgroundTasks,
2296
+ ) -> ResponseWithMessage:
2297
+ """Send batch email integrations for a privacy request."""
2298
+ background_tasks.add_task(send_email_batch)
2299
+
2300
+ return ResponseWithMessage(
2301
+ message="Email batch job started. This may take a few minutes to complete."
2302
+ )
@@ -142,6 +142,18 @@ TABLE_OBJECT_MAP: Dict[str, List[Dict[str, str]]] = {
142
142
  "type": "index",
143
143
  },
144
144
  ],
145
+ "stagedresource": [
146
+ {
147
+ "name": "ix_stagedresource_monitor_config_resource_type_consent",
148
+ "statement": "CREATE INDEX CONCURRENTLY ix_stagedresource_monitor_config_resource_type_consent ON stagedresource (monitor_config_id, resource_type, (meta->>'consent_aggregated'))",
149
+ "type": "index",
150
+ },
151
+ {
152
+ "name": "ix_stagedresource_system_vendor_consent",
153
+ "statement": "CREATE INDEX CONCURRENTLY ix_stagedresource_system_vendor_consent ON stagedresource (system_id, vendor_id, (meta->>'consent_aggregated'))",
154
+ "type": "index",
155
+ },
156
+ ],
145
157
  }
146
158
 
147
159
 
fides/api/models/asset.py CHANGED
@@ -1,10 +1,10 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from enum import Enum
3
4
  from typing import Any, Dict, Optional, Type
4
5
 
5
6
  from sqlalchemy import (
6
7
  ARRAY,
7
- BOOLEAN,
8
8
  Column,
9
9
  ForeignKey,
10
10
  Index,
@@ -20,9 +20,21 @@ from sqlalchemy.ext.mutable import MutableDict
20
20
  from sqlalchemy.orm import relationship
21
21
 
22
22
  from fides.api.db.base_class import Base
23
+ from fides.api.db.util import EnumColumn
23
24
  from fides.api.models.sql_models import System # type: ignore[attr-defined]
24
25
 
25
26
 
27
+ class ConsentStatus(str, Enum):
28
+ """
29
+ Consent status of the asset
30
+ """
31
+
32
+ with_consent = "with_consent"
33
+ without_consent = "without_consent"
34
+ exempt = "exempt"
35
+ unknown = "unknown"
36
+
37
+
26
38
  class Asset(Base):
27
39
  """
28
40
  Web assets associated with a system
@@ -35,7 +47,12 @@ class Asset(Base):
35
47
  parent = Column(ARRAY(String), server_default="{}", nullable=False)
36
48
  parent_domain = Column(String)
37
49
  locations = Column(ARRAY(String), server_default="{}", nullable=False)
38
- with_consent = Column(BOOLEAN, default=False, nullable=False)
50
+ consent_status = Column(
51
+ EnumColumn(ConsentStatus, native_enum=True),
52
+ default=ConsentStatus.unknown,
53
+ server_default="unknown",
54
+ nullable=False,
55
+ )
39
56
  data_uses = Column(ARRAY(String), server_default="{}", nullable=False)
40
57
  description = Column(String, nullable=True)
41
58
  page = Column(ARRAY(String), server_default="{}", nullable=False)
@@ -70,6 +70,8 @@ class ConnectionType(enum.Enum):
70
70
  sovrn = "sovrn"
71
71
  timescale = "timescale"
72
72
  website = "website"
73
+ # Test connection types, used for testing purposes only
74
+ test_website = "test_website" # used for ConfigurableTesteWebsiteMonitor
73
75
 
74
76
  @property
75
77
  def human_readable(self) -> str:
@@ -107,6 +109,7 @@ class ConnectionType(enum.Enum):
107
109
  ConnectionType.sovrn.value: "Sovrn",
108
110
  ConnectionType.timescale.value: "TimescaleDB",
109
111
  ConnectionType.website.value: "Website",
112
+ ConnectionType.test_website.value: "Test Website Connector -- not for production use",
110
113
  }
111
114
  try:
112
115
  return readable_mapping[self.value]
@@ -152,6 +155,7 @@ class ConnectionType(enum.Enum):
152
155
  ConnectionType.sovrn.value: SystemType.email,
153
156
  ConnectionType.timescale.value: SystemType.database,
154
157
  ConnectionType.website.value: SystemType.website,
158
+ ConnectionType.test_website.value: SystemType.website,
155
159
  }
156
160
 
157
161
  try:
@@ -530,6 +530,23 @@ class StagedResource(Base):
530
530
  default=dict,
531
531
  )
532
532
 
533
+ __table_args__ = (
534
+ # Used for querying monitor aggregates
535
+ Index(
536
+ "ix_stagedresource_monitor_config_resource_type_consent",
537
+ "monitor_config_id",
538
+ "resource_type",
539
+ text("(meta->>'consent_aggregated')"),
540
+ ),
541
+ # Used for querying system aggregates
542
+ Index(
543
+ "ix_stagedresource_system_vendor_consent",
544
+ "system_id",
545
+ "vendor_id",
546
+ text("(meta->>'consent_aggregated')"),
547
+ ),
548
+ )
549
+
533
550
  @classmethod
534
551
  def get_urn(cls, db: Session, urn: str) -> Optional[StagedResource]:
535
552
  """Utility to retrieve the staged resource with the given URN"""
fides/api/oauth/roles.py CHANGED
@@ -27,6 +27,7 @@ from fides.common.api.scope_registry import (
27
27
  PRIVACY_NOTICE_READ,
28
28
  PRIVACY_REQUEST_CALLBACK_RESUME,
29
29
  PRIVACY_REQUEST_DELETE,
30
+ PRIVACY_REQUEST_EMAIL_INTEGRATIONS_SEND,
30
31
  PRIVACY_REQUEST_MANUAL_STEPS_RESPOND,
31
32
  PRIVACY_REQUEST_MANUAL_STEPS_REVIEW,
32
33
  PRIVACY_REQUEST_NOTIFICATIONS_CREATE_OR_UPDATE,
@@ -138,6 +139,7 @@ not_contributor_scopes = [
138
139
  MESSAGING_CREATE_OR_UPDATE,
139
140
  MESSAGING_DELETE,
140
141
  PRIVACY_REQUEST_NOTIFICATIONS_CREATE_OR_UPDATE,
142
+ PRIVACY_REQUEST_EMAIL_INTEGRATIONS_SEND,
141
143
  USER_PERMISSION_ASSIGN_OWNERS,
142
144
  ]
143
145
 
fides/api/schemas/api.py CHANGED
@@ -24,6 +24,12 @@ class BulkResponse(BaseModel):
24
24
  )
25
25
 
26
26
 
27
+ class ResponseWithMessage(BaseModel):
28
+ """Generic schema for responses with a message"""
29
+
30
+ message: str
31
+
32
+
27
33
  class BulkUpdateFailed(BaseModel):
28
34
  """Schema for use when Bulk Create/Update fails."""
29
35
 
@@ -191,6 +191,7 @@ secrets_schemas: Dict[str, Any] = {
191
191
  ConnectionType.sovrn.value: SovrnSchema,
192
192
  ConnectionType.timescale.value: TimescaleSchema,
193
193
  ConnectionType.website.value: WebsiteSchema,
194
+ ConnectionType.test_website.value: WebsiteSchema,
194
195
  }
195
196
 
196
197
 
@@ -113,6 +113,7 @@ supported_connectors: Dict[str, Any] = {
113
113
  ConnectionType.sovrn.value: SovrnConnector,
114
114
  ConnectionType.timescale.value: TimescaleConnector,
115
115
  ConnectionType.website.value: WebsiteConnector,
116
+ ConnectionType.test_website.value: WebsiteConnector,
116
117
  }
117
118
 
118
119
 
@@ -38,7 +38,7 @@ class BaseEmailConnector(Generic[DB_CONNECTOR_TYPE], ABC):
38
38
  """
39
39
 
40
40
  @abstractmethod
41
- def batch_email_send(self, privacy_requests: Query) -> None:
41
+ def batch_email_send(self, privacy_requests: Query, batch_id: str) -> None:
42
42
  """
43
43
  Aggregates the identities provided by multiple privacy requests and sends them in a single batch email.
44
44
  """
@@ -1,6 +1,6 @@
1
- from typing import Any, Dict, List
1
+ from typing import Any, Dict, List, Optional
2
2
 
3
- from sqlalchemy.orm import Session
3
+ from sqlalchemy.orm import Query, Session
4
4
 
5
5
  from fides.api.models.connectionconfig import ConnectionConfig, ConnectionType
6
6
  from fides.api.models.policy import Rule
@@ -16,6 +16,7 @@ from fides.api.schemas.messaging.messaging import (
16
16
  MessagingActionType,
17
17
  )
18
18
  from fides.api.schemas.policy import ActionType
19
+ from fides.api.schemas.privacy_request import PrivacyRequestStatus
19
20
  from fides.api.schemas.redis_cache import Identity
20
21
  from fides.api.service.connectors.base_email_connector import (
21
22
  BaseEmailConnector,
@@ -81,6 +82,42 @@ class BaseErasureEmailConnector(BaseEmailConnector):
81
82
  },
82
83
  )
83
84
 
85
+ def error_privacy_request(
86
+ self,
87
+ db: Session,
88
+ privacy_request: PrivacyRequest,
89
+ failure_reason: Optional[str],
90
+ ) -> None:
91
+ """
92
+ Creates an ExecutionLog with status error for the privacy request, using the failure_reason
93
+ as the message, and sets the privacy request status to error.
94
+ """
95
+ ExecutionLog.create(
96
+ db=db,
97
+ data={
98
+ "connection_key": self.configuration.key,
99
+ "dataset_name": self.configuration.name_or_key,
100
+ "collection_name": self.configuration.name_or_key,
101
+ "privacy_request_id": privacy_request.id,
102
+ "action_type": ActionType.erasure,
103
+ "status": ExecutionLogStatus.error,
104
+ "message": failure_reason
105
+ or "An error occurred when trying to send the erasure email",
106
+ },
107
+ )
108
+ privacy_request.status = PrivacyRequestStatus.error
109
+ privacy_request.save(db)
110
+
111
+ def error_all_privacy_requests(
112
+ self, db: Session, privacy_requests: Query, failure_reason: str
113
+ ) -> None:
114
+ """
115
+ Creates an ExecutionLog with status error for each privacy request in the batch, and sets the
116
+ privacy request status to error.
117
+ """
118
+ for privacy_request in privacy_requests:
119
+ self.error_privacy_request(db, privacy_request, failure_reason)
120
+
84
121
 
85
122
  def get_identity_types_for_connector(
86
123
  email_secrets: BaseEmailSchema,
@@ -212,7 +212,7 @@ class GenericConsentEmailConnector(BaseEmailConnector):
212
212
  db, privacy_request, self.configuration
213
213
  )
214
214
 
215
- def batch_email_send(self, privacy_requests: Query) -> None:
215
+ def batch_email_send(self, privacy_requests: Query, batch_id: str) -> None:
216
216
  db = Session.object_session(self.configuration)
217
217
 
218
218
  skipped_privacy_requests: List[str] = []
@@ -22,7 +22,6 @@ from fides.api.schemas.connection_configuration.connection_secrets_dynamic_erasu
22
22
  DynamicErasureEmailSchema,
23
23
  )
24
24
  from fides.api.schemas.policy import ActionType
25
- from fides.api.schemas.privacy_request import PrivacyRequestStatus
26
25
  from fides.api.service.connectors.base_connector import BaseConnector
27
26
  from fides.api.service.connectors.base_erasure_email_connector import (
28
27
  BaseErasureEmailConnector,
@@ -67,9 +66,11 @@ class DynamicErasureEmailConnector(BaseErasureEmailConnector):
67
66
  def get_config(self, configuration: ConnectionConfig) -> DynamicErasureEmailSchema:
68
67
  return DynamicErasureEmailSchema(**configuration.secrets or {})
69
68
 
70
- def batch_email_send(self, privacy_requests: Query) -> None:
69
+ def batch_email_send(self, privacy_requests: Query, batch_id: str) -> None:
71
70
  logger.debug(
72
- "Starting batch_email_send for connector: {} ...", self.configuration.key
71
+ "Starting batch erasure email {} for connector: {} ...",
72
+ batch_id,
73
+ self.configuration.key,
73
74
  )
74
75
 
75
76
  db: Session = Session.object_session(self.configuration)
@@ -133,14 +134,16 @@ class DynamicErasureEmailConnector(BaseErasureEmailConnector):
133
134
 
134
135
  if not batched_identities:
135
136
  logger.info(
136
- "Skipping erasure email send for connector: '{}'. "
137
+ "Skipping erasure email send for connector '{}' and batch '{}'. "
137
138
  "No corresponding user identities or email addresses found for pending privacy requests.",
138
139
  self.configuration.key,
140
+ batch_id,
139
141
  )
140
142
  return
141
143
 
142
144
  logger.info(
143
- "Sending batched erasure email for connector {}...",
145
+ "Sending batch erasure email {} for connector {}...",
146
+ batch_id,
144
147
  self.configuration.key,
145
148
  )
146
149
 
@@ -155,15 +158,14 @@ class DynamicErasureEmailConnector(BaseErasureEmailConnector):
155
158
  test_mode=False,
156
159
  )
157
160
  except MessageDispatchException as exc:
158
- logger.error(
159
- "Dynamic erasure email for connector {} failed with exception {}",
160
- self.configuration.key,
161
- exc,
162
- )
161
+ message = f"Dynamic batch erasure email {batch_id} for connector {self.configuration.key} failed with exception {exc}"
162
+ logger.error(message)
163
163
  self.error_all_privacy_requests(
164
164
  db,
165
- privacy_requests,
166
- f"Dynamic erasure email for connector failed with MessageDispatchException. Error: {exc}",
165
+ privacy_requests.filter(
166
+ PrivacyRequest.id.notin_(skipped_privacy_requests)
167
+ ),
168
+ message,
167
169
  )
168
170
  raise exc
169
171
 
@@ -470,42 +472,6 @@ class DynamicErasureEmailConnector(BaseErasureEmailConnector):
470
472
 
471
473
  return email, vendor
472
474
 
473
- def error_all_privacy_requests(
474
- self, db: Session, privacy_requests: Query, failure_reason: str
475
- ) -> None:
476
- """
477
- Creates an ExecutionLog with status error for each privacy request in the batch, and sets the
478
- privacy request status to error.
479
- """
480
- for privacy_request in privacy_requests:
481
- self.error_privacy_request(db, privacy_request, failure_reason)
482
-
483
- def error_privacy_request(
484
- self,
485
- db: Session,
486
- privacy_request: PrivacyRequest,
487
- failure_reason: Optional[str],
488
- ) -> None:
489
- """
490
- Creates an ExecutionLog with status error for the privacy request, using the failure_reason
491
- as the message, and sets the privacy request status to error.
492
- """
493
- ExecutionLog.create(
494
- db=db,
495
- data={
496
- "connection_key": self.configuration.key,
497
- "dataset_name": self.configuration.name_or_key,
498
- "collection_name": self.configuration.name_or_key,
499
- "privacy_request_id": privacy_request.id,
500
- "action_type": ActionType.erasure,
501
- "status": ExecutionLogStatus.error,
502
- "message": failure_reason
503
- or "An error occurred when trying to send the erasure email",
504
- },
505
- )
506
- privacy_request.status = PrivacyRequestStatus.error
507
- privacy_request.save(db)
508
-
509
475
  def test_connection(self) -> Optional[ConnectionTestStatus]:
510
476
  """
511
477
  Sends an email to the "test_email" configured, just to establish that the email workflow is working.
@@ -9,7 +9,7 @@ from fides.api.models.connectionconfig import (
9
9
  ConnectionTestStatus,
10
10
  ConnectionType,
11
11
  )
12
- from fides.api.models.privacy_request import ExecutionLog
12
+ from fides.api.models.privacy_request import ExecutionLog, PrivacyRequest
13
13
  from fides.api.models.worker_task import ExecutionLogStatus
14
14
  from fides.api.schemas.connection_configuration import EmailSchema
15
15
  from fides.api.schemas.policy import ActionType
@@ -67,7 +67,7 @@ class GenericErasureEmailConnector(BaseErasureEmailConnector):
67
67
  return ConnectionTestStatus.failed
68
68
  return ConnectionTestStatus.succeeded
69
69
 
70
- def batch_email_send(self, privacy_requests: Query) -> None:
70
+ def batch_email_send(self, privacy_requests: Query, batch_id: str) -> None:
71
71
  skipped_privacy_requests: List[str] = []
72
72
  batched_identities: List[str] = []
73
73
  db = Session.object_session(self.configuration)
@@ -85,14 +85,16 @@ class GenericErasureEmailConnector(BaseErasureEmailConnector):
85
85
 
86
86
  if not batched_identities:
87
87
  logger.info(
88
- "Skipping erasure email send for connector: '{}'. "
88
+ "Skipping erasure email send for connector '{}' and batch '{}'. "
89
89
  "No corresponding user identities found for pending privacy requests.",
90
90
  self.configuration.key,
91
+ batch_id,
91
92
  )
92
93
  return
93
94
 
94
95
  logger.info(
95
- "Sending batched erasure email for connector {}...",
96
+ "Sending batch erasure email {} for connector {}...",
97
+ batch_id,
96
98
  self.configuration.key,
97
99
  )
98
100
 
@@ -105,10 +107,14 @@ class GenericErasureEmailConnector(BaseErasureEmailConnector):
105
107
  test_mode=False,
106
108
  )
107
109
  except MessageDispatchException as exc:
108
- logger.info(
109
- "Erasure email for connector {} failed with exception {}",
110
- self.configuration.key,
111
- exc,
110
+ message = f"Batch erasure email {batch_id} for connector {self.configuration.key} failed with exception {exc}"
111
+ logger.error(message)
112
+ self.error_all_privacy_requests(
113
+ db,
114
+ privacy_requests.filter(
115
+ PrivacyRequest.id.notin_(skipped_privacy_requests)
116
+ ),
117
+ message,
112
118
  )
113
119
  raise
114
120