ethyca-fides 2.70.0rc5__py2.py3-none-any.whl → 2.70.1b0__py2.py3-none-any.whl

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

Potentially problematic release.


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

Files changed (205) hide show
  1. {ethyca_fides-2.70.0rc5.dist-info → ethyca_fides-2.70.1b0.dist-info}/METADATA +4 -4
  2. {ethyca_fides-2.70.0rc5.dist-info → ethyca_fides-2.70.1b0.dist-info}/RECORD +196 -195
  3. fides/_version.py +3 -3
  4. fides/api/api/v1/endpoints/system.py +5 -1
  5. fides/api/db/crud.py +30 -2
  6. fides/api/db/safe_crud.py +377 -0
  7. fides/api/models/policy.py +24 -0
  8. fides/api/models/privacy_notice.py +1 -1
  9. fides/api/models/privacy_request/privacy_request.py +62 -0
  10. fides/api/models/privacy_request/webhook.py +3 -1
  11. fides/api/schemas/connection_configuration/connection_secrets_mongodb.py +14 -2
  12. fides/api/service/connectors/mongodb_connector.py +74 -9
  13. fides/service/system/system_service.py +17 -2
  14. fides/ui-build/static/admin/404.html +1 -1
  15. fides/ui-build/static/admin/_next/static/{YDIHw7NCpEulNqL5G--Yh → 6oPWh0EXUTEVS_OTLA_S1}/_buildManifest.js +1 -1
  16. fides/ui-build/static/admin/_next/static/chunks/155-047c3806cc41295e.js +1 -0
  17. fides/ui-build/static/admin/_next/static/chunks/3700-865408b36fbee782.js +1 -0
  18. fides/ui-build/static/admin/_next/static/chunks/{7725-dd6736855807936a.js → 7725-fdc4298dfbea6f80.js} +1 -1
  19. fides/ui-build/static/admin/_next/static/chunks/7929-0fd0d4948bc8d70e.js +1 -0
  20. fides/ui-build/static/admin/_next/static/chunks/pages/{_app-e08a732e348aa667.js → _app-91cae6157e6f09b5.js} +1 -1
  21. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices-3ff2fd2570f02f1c.js +1 -0
  22. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{reporting-09be5455ba85db39.js → reporting-ae4909cad9b67822.js} +1 -1
  23. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-3d03cd31cd99fa07.js +1 -0
  24. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/{[monitorId]-0e4d9ff89c63793c.js → [monitorId]-b74dfaf4f4126e57.js} +1 -1
  25. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/{[id]-8b13bb5f7bee61c6.js → [id]-9f6c82e14ff2cad2.js} +1 -1
  26. fides/ui-build/static/admin/_next/static/chunks/pages/{integrations-6f109ef64304ef59.js → integrations-ebc9c90fe99ee68d.js} +1 -1
  27. fides/ui-build/static/admin/_next/static/chunks/pages/reporting/datamap-5b423687e227ad4d.js +1 -0
  28. fides/ui-build/static/admin/_next/static/chunks/pages/systems-916238dcc0596957.js +1 -0
  29. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-616f5a7cbb99e46d.js +1 -0
  30. fides/ui-build/static/admin/_next/static/css/1866822702989bb3.css +1 -0
  31. fides/ui-build/static/admin/add-systems/manual.html +1 -1
  32. fides/ui-build/static/admin/add-systems/multiple.html +1 -1
  33. fides/ui-build/static/admin/add-systems.html +1 -1
  34. fides/ui-build/static/admin/consent/configure/add-vendors.html +1 -1
  35. fides/ui-build/static/admin/consent/configure.html +1 -1
  36. fides/ui-build/static/admin/consent/privacy-experience/[id].html +1 -1
  37. fides/ui-build/static/admin/consent/privacy-experience/new.html +1 -1
  38. fides/ui-build/static/admin/consent/privacy-experience.html +1 -1
  39. fides/ui-build/static/admin/consent/privacy-notices/[id].html +1 -1
  40. fides/ui-build/static/admin/consent/privacy-notices/new.html +1 -1
  41. fides/ui-build/static/admin/consent/privacy-notices.html +1 -1
  42. fides/ui-build/static/admin/consent/properties.html +1 -1
  43. fides/ui-build/static/admin/consent/reporting.html +1 -1
  44. fides/ui-build/static/admin/consent.html +1 -1
  45. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn].html +1 -1
  46. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn].html +1 -1
  47. fides/ui-build/static/admin/data-catalog/[systemId]/projects.html +1 -1
  48. fides/ui-build/static/admin/data-catalog/[systemId]/resources/[resourceUrn].html +1 -1
  49. fides/ui-build/static/admin/data-catalog/[systemId]/resources.html +1 -1
  50. fides/ui-build/static/admin/data-catalog.html +1 -1
  51. fides/ui-build/static/admin/data-discovery/action-center/[monitorId]/[systemId].html +1 -1
  52. fides/ui-build/static/admin/data-discovery/action-center/[monitorId].html +1 -1
  53. fides/ui-build/static/admin/data-discovery/action-center.html +1 -1
  54. fides/ui-build/static/admin/data-discovery/activity.html +1 -1
  55. fides/ui-build/static/admin/data-discovery/detection/[resourceUrn].html +1 -1
  56. fides/ui-build/static/admin/data-discovery/detection.html +1 -1
  57. fides/ui-build/static/admin/data-discovery/discovery/[resourceUrn].html +1 -1
  58. fides/ui-build/static/admin/data-discovery/discovery.html +1 -1
  59. fides/ui-build/static/admin/datamap.html +1 -1
  60. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName]/[...subfieldNames].html +1 -1
  61. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName].html +1 -1
  62. fides/ui-build/static/admin/dataset/[datasetId].html +1 -1
  63. fides/ui-build/static/admin/dataset/new.html +1 -1
  64. fides/ui-build/static/admin/dataset.html +1 -1
  65. fides/ui-build/static/admin/datastore-connection/[id].html +1 -1
  66. fides/ui-build/static/admin/datastore-connection/new.html +1 -1
  67. fides/ui-build/static/admin/datastore-connection.html +1 -1
  68. fides/ui-build/static/admin/index.html +1 -1
  69. fides/ui-build/static/admin/integrations/[id].html +1 -1
  70. fides/ui-build/static/admin/integrations.html +1 -1
  71. fides/ui-build/static/admin/login/[provider].html +1 -1
  72. fides/ui-build/static/admin/login.html +1 -1
  73. fides/ui-build/static/admin/messaging/[id].html +1 -1
  74. fides/ui-build/static/admin/messaging/add-template.html +1 -1
  75. fides/ui-build/static/admin/messaging.html +1 -1
  76. fides/ui-build/static/admin/poc/ant-components.html +1 -1
  77. fides/ui-build/static/admin/poc/form-experiments/AntForm.html +1 -1
  78. fides/ui-build/static/admin/poc/form-experiments/FormikAntFormItem.html +1 -1
  79. fides/ui-build/static/admin/poc/form-experiments/FormikControlled.html +1 -1
  80. fides/ui-build/static/admin/poc/form-experiments/FormikField.html +1 -1
  81. fides/ui-build/static/admin/poc/form-experiments/FormikSpreadField.html +1 -1
  82. fides/ui-build/static/admin/poc/forms.html +1 -1
  83. fides/ui-build/static/admin/poc/table-migration.html +1 -1
  84. fides/ui-build/static/admin/privacy-requests/[id].html +1 -1
  85. fides/ui-build/static/admin/privacy-requests/configure/storage.html +1 -1
  86. fides/ui-build/static/admin/privacy-requests/configure.html +1 -1
  87. fides/ui-build/static/admin/privacy-requests.html +1 -1
  88. fides/ui-build/static/admin/properties/[id].html +1 -1
  89. fides/ui-build/static/admin/properties/add-property.html +1 -1
  90. fides/ui-build/static/admin/properties.html +1 -1
  91. fides/ui-build/static/admin/reporting/datamap.html +1 -1
  92. fides/ui-build/static/admin/settings/about/alpha.html +1 -1
  93. fides/ui-build/static/admin/settings/about.html +1 -1
  94. fides/ui-build/static/admin/settings/consent/[configuration_id]/[purpose_id].html +1 -1
  95. fides/ui-build/static/admin/settings/consent.html +1 -1
  96. fides/ui-build/static/admin/settings/custom-fields.html +1 -1
  97. fides/ui-build/static/admin/settings/domain-records.html +1 -1
  98. fides/ui-build/static/admin/settings/domains.html +1 -1
  99. fides/ui-build/static/admin/settings/email-templates.html +1 -1
  100. fides/ui-build/static/admin/settings/locations.html +1 -1
  101. fides/ui-build/static/admin/settings/messaging-providers/[key].html +1 -1
  102. fides/ui-build/static/admin/settings/messaging-providers/new.html +1 -1
  103. fides/ui-build/static/admin/settings/messaging-providers.html +1 -1
  104. fides/ui-build/static/admin/settings/organization.html +1 -1
  105. fides/ui-build/static/admin/settings/privacy-requests.html +1 -1
  106. fides/ui-build/static/admin/settings/regulations.html +1 -1
  107. fides/ui-build/static/admin/systems/configure/[id]/test-datasets.html +1 -1
  108. fides/ui-build/static/admin/systems/configure/[id].html +1 -1
  109. fides/ui-build/static/admin/systems.html +1 -1
  110. fides/ui-build/static/admin/taxonomy.html +1 -1
  111. fides/ui-build/static/admin/user-management/new.html +1 -1
  112. fides/ui-build/static/admin/user-management/profile/[id].html +1 -1
  113. fides/ui-build/static/admin/user-management.html +1 -1
  114. fides/ui-build/static/admin/_next/static/chunks/155-88303b05c6e115a5.js +0 -1
  115. fides/ui-build/static/admin/_next/static/chunks/3700-2a7094f112a1608a.js +0 -1
  116. fides/ui-build/static/admin/_next/static/chunks/7929-919e2dff24e40397.js +0 -1
  117. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices-8fb92df30e8d496a.js +0 -1
  118. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-758d51b4d37dbd09.js +0 -1
  119. fides/ui-build/static/admin/_next/static/chunks/pages/reporting/datamap-0afb12096a35ab78.js +0 -1
  120. fides/ui-build/static/admin/_next/static/chunks/pages/systems-ae3f3470e2734933.js +0 -1
  121. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-1b9c4b2749e3ece4.js +0 -1
  122. fides/ui-build/static/admin/_next/static/css/018c12b58ee7f861.css +0 -1
  123. {ethyca_fides-2.70.0rc5.dist-info → ethyca_fides-2.70.1b0.dist-info}/WHEEL +0 -0
  124. {ethyca_fides-2.70.0rc5.dist-info → ethyca_fides-2.70.1b0.dist-info}/entry_points.txt +0 -0
  125. {ethyca_fides-2.70.0rc5.dist-info → ethyca_fides-2.70.1b0.dist-info}/licenses/LICENSE +0 -0
  126. {ethyca_fides-2.70.0rc5.dist-info → ethyca_fides-2.70.1b0.dist-info}/top_level.txt +0 -0
  127. /fides/ui-build/static/admin/_next/static/{YDIHw7NCpEulNqL5G--Yh → 6oPWh0EXUTEVS_OTLA_S1}/_ssgManifest.js +0 -0
  128. /fides/ui-build/static/admin/_next/static/chunks/{1115-7888473b3dc28cda.js → 1115-90baef2a89f361ad.js} +0 -0
  129. /fides/ui-build/static/admin/_next/static/chunks/{1817-ee9e29a6b8c4af50.js → 1817-dbde9966025d7970.js} +0 -0
  130. /fides/ui-build/static/admin/_next/static/chunks/{2040-ab6212a3074f34f9.js → 2040-fdecc41a18e40bdc.js} +0 -0
  131. /fides/ui-build/static/admin/_next/static/chunks/{3696-c25dc8d1b0e1aee1.js → 3696-90c8b336bbc46782.js} +0 -0
  132. /fides/ui-build/static/admin/_next/static/chunks/{3872-3514b712afd683c0.js → 3872-04d3afbfa41a7782.js} +0 -0
  133. /fides/ui-build/static/admin/_next/static/chunks/{4608-96f480766541124b.js → 4608-63fbb1f4f258a66e.js} +0 -0
  134. /fides/ui-build/static/admin/_next/static/chunks/{502-a40d39e615f7b664.js → 502-d3ecae97b67befbd.js} +0 -0
  135. /fides/ui-build/static/admin/_next/static/chunks/{5185-33f50cf9ae17b42e.js → 5185-51eaa78e3ed6bfb7.js} +0 -0
  136. /fides/ui-build/static/admin/_next/static/chunks/{5574-b8c4cba5a6938c00.js → 5574-c31ea831371610d5.js} +0 -0
  137. /fides/ui-build/static/admin/_next/static/chunks/{5783-8de76df87af55e98.js → 5783-8f5713517ebc35f3.js} +0 -0
  138. /fides/ui-build/static/admin/_next/static/chunks/{6084-2cd165179c428a6f.js → 6084-dc473a58c3e2889b.js} +0 -0
  139. /fides/ui-build/static/admin/_next/static/chunks/{6416-18d438ff85d807f8.js → 6416-39d12ffc78833cb1.js} +0 -0
  140. /fides/ui-build/static/admin/_next/static/chunks/{6882-447f15e87b8c48a5.js → 6882-10296485ec326e6b.js} +0 -0
  141. /fides/ui-build/static/admin/_next/static/chunks/{6954-599f2de2c902e9b2.js → 6954-4b24e1731c1cc3b3.js} +0 -0
  142. /fides/ui-build/static/admin/_next/static/chunks/{7158-835ba42fd881d8dd.js → 7158-04745cc8d684b2e7.js} +0 -0
  143. /fides/ui-build/static/admin/_next/static/chunks/{7476-0b6e114658b15eaa.js → 7476-c709d0610ebf7e2e.js} +0 -0
  144. /fides/ui-build/static/admin/_next/static/chunks/{7630-e7ea13be69c118a1.js → 7630-d0d3a0fe3f95e971.js} +0 -0
  145. /fides/ui-build/static/admin/_next/static/chunks/{796-e07ac2c543f569e3.js → 796-876998c86754da97.js} +0 -0
  146. /fides/ui-build/static/admin/_next/static/chunks/{8002-25fd174aec9b077b.js → 8002-ed832921ad190832.js} +0 -0
  147. /fides/ui-build/static/admin/_next/static/chunks/{9226-2f960b7ca530642a.js → 9226-4a7027057f55ca2a.js} +0 -0
  148. /fides/ui-build/static/admin/_next/static/chunks/{9826-c02be5882205bbbc.js → 9826-ccedc28e978ca9e1.js} +0 -0
  149. /fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{manual-939253f8daf349b2.js → manual-16ecb33f09224fbb.js} +0 -0
  150. /fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{multiple-83ed7da0bb90b0a5.js → multiple-2ca59996860a33c5.js} +0 -0
  151. /fides/ui-build/static/admin/_next/static/chunks/pages/{add-systems-f90aa48500c1cbde.js → add-systems-caff552fce501f82.js} +0 -0
  152. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure/{add-vendors-46b88bda3d7b15c5.js → add-vendors-7a258b7ecd6da4b8.js} +0 -0
  153. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{configure-c0db068d1863222f.js → configure-259ad2e10fe6f413.js} +0 -0
  154. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-experience-92a337ee96845af2.js → privacy-experience-7e78616b7b048978.js} +0 -0
  155. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{[id]-1fd2cda8707314f6.js → [id]-9c23fbe813c997d0.js} +0 -0
  156. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{new-2987e397445713c5.js → new-0e5e38bbcfe59fd2.js} +0 -0
  157. /fides/ui-build/static/admin/_next/static/chunks/pages/{consent-e5a33654a2dfaf35.js → consent-d2bf72508c3cad55.js} +0 -0
  158. /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]/{[resourceUrn]-293c1f2d9aefb447.js → [resourceUrn]-06a08970907ed3f0.js} +0 -0
  159. /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/{[projectUrn]-6a4b0d49dcbf17a8.js → [projectUrn]-4a1af12d2d7cd660.js} +0 -0
  160. /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{projects-be7b385073f22414.js → projects-99573a1ee3ef8f4c.js} +0 -0
  161. /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/resources/{[resourceUrn]-18501152fa1e4f40.js → [resourceUrn]-4c84d952bb1db690.js} +0 -0
  162. /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{resources-af80fdca3bbdc82f.js → resources-6e429b7511028d60.js} +0 -0
  163. /fides/ui-build/static/admin/_next/static/chunks/pages/{data-catalog-351caadeef03876a.js → data-catalog-56fd0f3e465e52b6.js} +0 -0
  164. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{action-center-1554afcb8b9da2ab.js → action-center-040813022f0890c9.js} +0 -0
  165. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/detection/{[resourceUrn]-0497f3ffdb632516.js → [resourceUrn]-844a8de0d1b506e2.js} +0 -0
  166. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{detection-a780390da99f3e43.js → detection-11b07cf2d91b17ef.js} +0 -0
  167. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/discovery/{[resourceUrn]-1901c26cdde820da.js → [resourceUrn]-65dc7f5a2ce3eae7.js} +0 -0
  168. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{discovery-0cea22af5929c81f.js → discovery-4d378516817cf00b.js} +0 -0
  169. /fides/ui-build/static/admin/_next/static/chunks/pages/{datamap-619f27c745188adb.js → datamap-4a05303416dcb657.js} +0 -0
  170. /fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/{[...subfieldNames]-ef71f387fbbab425.js → [...subfieldNames]-d4031e438c363fff.js} +0 -0
  171. /fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/{[collectionName]-d790553662caf5c3.js → [collectionName]-9463af37079762d0.js} +0 -0
  172. /fides/ui-build/static/admin/_next/static/chunks/pages/dataset/{[datasetId]-cb63db8594fe8dc1.js → [datasetId]-60a4a9eb4aab4c11.js} +0 -0
  173. /fides/ui-build/static/admin/_next/static/chunks/pages/dataset/{new-78e052c8f95110c4.js → new-910e28bce6a98f3d.js} +0 -0
  174. /fides/ui-build/static/admin/_next/static/chunks/pages/{dataset-d6d7ee8bd8858a8a.js → dataset-108630926347724e.js} +0 -0
  175. /fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{[id]-cc149157d290a94d.js → [id]-5119e6602507157f.js} +0 -0
  176. /fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{new-4c9fb068a5561658.js → new-cda4e7b5b888e17c.js} +0 -0
  177. /fides/ui-build/static/admin/_next/static/chunks/pages/{datastore-connection-a832084ce294f8af.js → datastore-connection-223c2d1ded51bfb1.js} +0 -0
  178. /fides/ui-build/static/admin/_next/static/chunks/pages/{index-269b8f81546dad66.js → index-b74d1e8608ae5b5d.js} +0 -0
  179. /fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{[id]-d8c5c03fb2f31d65.js → [id]-e8d2140787045acd.js} +0 -0
  180. /fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{add-template-0e0c06e3c8aabe02.js → add-template-e3f93462a08251bf.js} +0 -0
  181. /fides/ui-build/static/admin/_next/static/chunks/pages/{messaging-3f15804cf9625f01.js → messaging-b5f7d6afdecd013d.js} +0 -0
  182. /fides/ui-build/static/admin/_next/static/chunks/pages/poc/{table-migration-e551fccfcaae76e7.js → table-migration-329333a88f3826eb.js} +0 -0
  183. /fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/{[id]-8566e3b7b2a632fa.js → [id]-989c77898de2da75.js} +0 -0
  184. /fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/{storage-1b38b656807ed0cd.js → storage-648d775d0fce49dc.js} +0 -0
  185. /fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/{configure-b00532a0ad4f6927.js → configure-8f577df28ebca869.js} +0 -0
  186. /fides/ui-build/static/admin/_next/static/chunks/pages/{privacy-requests-65f0d5672041a202.js → privacy-requests-14a2efa72f0d4d12.js} +0 -0
  187. /fides/ui-build/static/admin/_next/static/chunks/pages/properties/{[id]-322a01e2bceab3fb.js → [id]-57a75c7e9659271a.js} +0 -0
  188. /fides/ui-build/static/admin/_next/static/chunks/pages/properties/{add-property-777ed2d73812043d.js → add-property-8964c2300206bc89.js} +0 -0
  189. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{consent-55e36839d219a503.js → consent-1ae1257f5b388924.js} +0 -0
  190. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{custom-fields-26ce8fc493993765.js → custom-fields-c2f1376aca192114.js} +0 -0
  191. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domain-records-7ddf9d992fe714a6.js → domain-records-586505df9d853f1f.js} +0 -0
  192. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domains-7c78ae51f0dd7102.js → domains-a3275554ffe8e640.js} +0 -0
  193. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{email-templates-05ffbda19ab894b9.js → email-templates-604790638c656fbd.js} +0 -0
  194. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{locations-77fb85bdd0be42b5.js → locations-be2a885150adc133.js} +0 -0
  195. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/messaging-providers/{[key]-b0d93bf478bf63ee.js → [key]-8df31428446a6a96.js} +0 -0
  196. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/messaging-providers/{new-084f9756b9987285.js → new-af1471bf4571d5d3.js} +0 -0
  197. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{messaging-providers-6c51ffd46bb598e7.js → messaging-providers-8d92be437793c96f.js} +0 -0
  198. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{organization-44456bfe54ac4ad5.js → organization-3c86162afe9759df.js} +0 -0
  199. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{privacy-requests-fbe7e8030d837aed.js → privacy-requests-8cbdfd08e0fa88fb.js} +0 -0
  200. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{regulations-2866ac99faa5a542.js → regulations-4fe3b90747d885e5.js} +0 -0
  201. /fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/{test-datasets-a86bafe1b4e1205f.js → test-datasets-2deb6becece69d46.js} +0 -0
  202. /fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/{[id]-1895c6a13b543436.js → [id]-589952aa1a31c33d.js} +0 -0
  203. /fides/ui-build/static/admin/_next/static/chunks/pages/user-management/{new-6304dad2c5fab694.js → new-629c88e90699369b.js} +0 -0
  204. /fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/{[id]-ff4711db191099cd.js → [id]-98f737e735eaa0f0.js} +0 -0
  205. /fides/ui-build/static/admin/_next/static/chunks/pages/{user-management-82fcf1151e2fe2ba.js → user-management-562624e5461083ec.js} +0 -0
fides/_version.py CHANGED
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2025-09-12T11:27:49-0300",
11
+ "date": "2025-09-17T11:54:23-0700",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "18d4179893f3166051eda599dc5c257d7dc34839",
15
- "version": "2.70.0rc5"
14
+ "full-revisionid": "f42db9940a5b753019726d317e93e58db908e929",
15
+ "version": "2.70.1b0"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -1,4 +1,4 @@
1
- from typing import Annotated, Dict, List, Optional, Union
1
+ from typing import Annotated, Dict, List, Literal, Optional, Union
2
2
 
3
3
  from fastapi import Depends, HTTPException, Query, Response, Security
4
4
  from fastapi_pagination import Page, Params
@@ -509,6 +509,8 @@ async def ls( # pylint: disable=invalid-name
509
509
  data_categories: Optional[List[FidesKey]] = Query(None),
510
510
  data_subjects: Optional[List[FidesKey]] = Query(None),
511
511
  show_deleted: bool = Query(False),
512
+ sort_by: Optional[List[Literal["name"]]] = Query(None),
513
+ sort_asc: Optional[bool] = Query(True),
512
514
  ) -> Union[List[System], Page[System]]:
513
515
  """Get a list of all of the Systems.
514
516
  If any parameters or filters are provided the response will be paginated and/or filtered.
@@ -524,6 +526,8 @@ async def ls( # pylint: disable=invalid-name
524
526
  size=size,
525
527
  page=page,
526
528
  show_deleted=show_deleted,
529
+ sort_by=sort_by,
530
+ sort_asc=sort_asc,
527
531
  )
528
532
 
529
533
 
fides/api/db/crud.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """
2
- Contains all of the generic CRUD endpoints that can be
3
- generated programmatically for each resource.
2
+ DEPRECATED: This module uses manual transaction handling which can
3
+ lead to unexpected behavior. Use fides.api.db.safe_crud instead.
4
4
  """
5
5
 
6
6
  from collections import defaultdict
@@ -18,6 +18,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
18
18
  from sqlalchemy.future import select
19
19
  from sqlalchemy.sql import Select
20
20
  from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY
21
+ from typing_extensions import deprecated
21
22
 
22
23
  from fides.api.models.sql_models import ( # type: ignore[attr-defined]
23
24
  CustomField,
@@ -32,6 +33,9 @@ T = TypeVar("T", bound="FidesBase")
32
33
 
33
34
 
34
35
  # CRUD Functions
36
+ @deprecated(
37
+ "This function uses a manual session.begin() which can lead to unexpected transaction handling. Use create_resource from safe_crud instead."
38
+ )
35
39
  async def create_resource(
36
40
  sql_model: Type[T], resource_dict: Dict, async_session: AsyncSession
37
41
  ) -> T:
@@ -66,6 +70,9 @@ async def create_resource(
66
70
  return await get_resource(sql_model, resource_dict["fides_key"], async_session)
67
71
 
68
72
 
73
+ @deprecated(
74
+ "This function uses manual session.begin() which can lead to unexpected transaction handling. Use get_custom_fields_filtered from safe_crud instead."
75
+ )
69
76
  async def get_custom_fields_filtered(
70
77
  async_session: AsyncSession,
71
78
  resource_types_to_ids: Dict[ResourceTypes, List[str]] = defaultdict(list),
@@ -111,6 +118,9 @@ async def get_custom_fields_filtered(
111
118
  raise sa_error
112
119
 
113
120
 
121
+ @deprecated(
122
+ "This function uses manual session.begin() which can lead to unexpected transaction handling. Use get_resource from safe_crud instead."
123
+ )
114
124
  async def get_resource(
115
125
  sql_model: Type[T],
116
126
  fides_key: str,
@@ -142,6 +152,9 @@ async def get_resource(
142
152
  return sql_resource
143
153
 
144
154
 
155
+ @deprecated(
156
+ "This function uses manual session.begin() which can lead to unexpected transaction handling. Use get_resource_with_custom_fields from safe_crud instead."
157
+ )
145
158
  async def get_resource_with_custom_fields(
146
159
  sql_model: Type[T], fides_key: str, async_session: AsyncSession
147
160
  ) -> Dict[str, Any]:
@@ -193,6 +206,9 @@ async def get_resource_with_custom_fields(
193
206
  return resource_dict
194
207
 
195
208
 
209
+ @deprecated(
210
+ "This function uses manual session.begin() which can lead to unexpected transaction handling. Use list_resource from safe_crud instead."
211
+ )
196
212
  async def list_resource(sql_model: Type[T], async_session: AsyncSession) -> List[T]:
197
213
  """
198
214
  Get a list of all of the resources of this type from the database.
@@ -203,6 +219,9 @@ async def list_resource(sql_model: Type[T], async_session: AsyncSession) -> List
203
219
  return await list_resource_query(async_session, query, sql_model)
204
220
 
205
221
 
222
+ @deprecated(
223
+ "This function uses manual session.begin() which can lead to unexpected transaction handling. Use list_resource_query from safe_crud instead."
224
+ )
206
225
  async def list_resource_query(
207
226
  async_session: AsyncSession, query: Select, sql_model: Type[T]
208
227
  ) -> List[T]:
@@ -225,6 +244,9 @@ async def list_resource_query(
225
244
  return sql_resources
226
245
 
227
246
 
247
+ @deprecated(
248
+ "This function uses manual session.begin() which can lead to unexpected transaction handling. Use update_resource from safe_crud instead."
249
+ )
228
250
  async def update_resource(
229
251
  sql_model: Type[T], resource_dict: Dict, async_session: AsyncSession
230
252
  ) -> Dict:
@@ -251,6 +273,9 @@ async def update_resource(
251
273
  return await get_resource(sql_model, resource_dict["fides_key"], async_session)
252
274
 
253
275
 
276
+ @deprecated(
277
+ "This function uses manual session.begin() which can lead to unexpected transaction handling. Use upsert_resources from safe_crud instead."
278
+ )
254
279
  async def upsert_resources(
255
280
  sql_model: Type[T], resource_dicts: List[Dict], async_session: AsyncSession
256
281
  ) -> Tuple[int, int]:
@@ -300,6 +325,9 @@ async def upsert_resources(
300
325
  raise sa_error
301
326
 
302
327
 
328
+ @deprecated(
329
+ "This function uses manual session.begin() which can lead to unexpected transaction handling. Use delete_resource from safe_crud instead."
330
+ )
303
331
  async def delete_resource(
304
332
  sql_model: Type[T], fides_key: str, async_session: AsyncSession
305
333
  ) -> T:
@@ -0,0 +1,377 @@
1
+ """
2
+ This module contains "safe" versions of CRUD operations that do NOT
3
+ manually manage database transactions. Transaction management is left
4
+ to the calling code (endpoints, services) to handle at the appropriate
5
+ boundary.
6
+
7
+ Use functions from this module instead of fides.api.db.crud
8
+ """
9
+
10
+ from collections import defaultdict
11
+ from typing import Any, Dict, List, Tuple, Type, TypeVar
12
+
13
+ from fastapi import HTTPException
14
+ from loguru import logger as log
15
+ from sqlalchemy import and_, column
16
+ from sqlalchemy import delete as _delete
17
+ from sqlalchemy import or_
18
+ from sqlalchemy import update as _update
19
+ from sqlalchemy.dialects.postgresql import Insert as _insert
20
+ from sqlalchemy.exc import IntegrityError, SQLAlchemyError
21
+ from sqlalchemy.ext.asyncio import AsyncSession
22
+ from sqlalchemy.future import select
23
+ from sqlalchemy.sql import Select
24
+ from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY
25
+
26
+ from fides.api.models.sql_models import ( # type: ignore[attr-defined]
27
+ CustomField,
28
+ CustomFieldDefinition,
29
+ FidesBase,
30
+ ResourceTypes,
31
+ )
32
+ from fides.api.util import errors
33
+
34
+ # Helps return type be linked to the type of the parameter
35
+ T = TypeVar("T", bound="FidesBase")
36
+
37
+
38
+ # CRUD Functions
39
+ async def create_resource(
40
+ sql_model: Type[T], resource_dict: Dict, async_session: AsyncSession
41
+ ) -> T:
42
+ """
43
+ Create a resource in the database.
44
+
45
+ This version does NOT manually manage transactions - transaction management
46
+ is left to the calling code.
47
+ """
48
+ with log.contextualize(
49
+ sql_model=sql_model.__name__, fides_key=resource_dict["fides_key"]
50
+ ):
51
+
52
+ existing_resource = await get_resource(
53
+ sql_model, resource_dict["fides_key"], async_session, raise_not_found=False
54
+ )
55
+
56
+ if existing_resource is not None:
57
+ already_exists_error = errors.AlreadyExistsError(
58
+ sql_model.__name__, resource_dict["fides_key"]
59
+ )
60
+ log.bind(error=already_exists_error.detail["error"]).info( # type: ignore[index]
61
+ "Failed to insert resource"
62
+ )
63
+ raise already_exists_error
64
+
65
+ try:
66
+ log.debug("Creating resource")
67
+ query = _insert(sql_model.__table__).values(resource_dict)
68
+ await async_session.execute(query)
69
+ except SQLAlchemyError as e:
70
+ log.exception(f"Failed to create resource with error: '{e}'")
71
+ sa_error = errors.QueryError()
72
+ raise sa_error
73
+
74
+ return await get_resource(sql_model, resource_dict["fides_key"], async_session)
75
+
76
+
77
+ async def get_custom_fields_filtered(
78
+ async_session: AsyncSession,
79
+ resource_types_to_ids: Dict[ResourceTypes, List[str]] = defaultdict(list),
80
+ ) -> FidesBase:
81
+ """
82
+ Utility function to construct a filtered query for custom field values based on provided mapping of
83
+ resource types to resource IDs.
84
+
85
+ Only custom fields with an "active" CustomFieldDefinition are returned.
86
+
87
+ This is for use in bulk querying of custom fields, to avoid multiple round trips to the db.
88
+ """
89
+ with log.contextualize(model=CustomField):
90
+ try:
91
+ log.debug("Fetching resource")
92
+ query = select(
93
+ CustomField.resource_id,
94
+ CustomField.value,
95
+ CustomFieldDefinition.resource_type,
96
+ CustomFieldDefinition.name,
97
+ CustomFieldDefinition.field_type,
98
+ ).join(
99
+ CustomFieldDefinition,
100
+ CustomFieldDefinition.id == CustomField.custom_field_definition_id,
101
+ )
102
+
103
+ criteria = [
104
+ and_(
105
+ CustomFieldDefinition.resource_type == resource_type.value,
106
+ CustomField.resource_id.in_(resource_ids),
107
+ # pylint: disable=singleton-comparison
108
+ CustomFieldDefinition.active == True,
109
+ )
110
+ for resource_type, resource_ids in resource_types_to_ids.items()
111
+ ]
112
+ query = query.where(or_(False, *criteria))
113
+ result = await async_session.execute(query)
114
+ return result.mappings().all()
115
+ except SQLAlchemyError as e:
116
+ sa_error = errors.QueryError()
117
+ log.exception(f"Failed to fetch custom fields with error: '{e}'")
118
+ raise sa_error
119
+
120
+
121
+ async def get_resource(
122
+ sql_model: Type[T],
123
+ fides_key: str,
124
+ async_session: AsyncSession,
125
+ raise_not_found: bool = True,
126
+ ) -> T:
127
+ """
128
+ Get a resource from the database by its FidesKey.
129
+
130
+ Returns a SQLAlchemy model of that resource.
131
+
132
+ This version does NOT manually manage transactions - transaction management
133
+ is left to the calling code.
134
+ """
135
+ with log.contextualize(sql_model=sql_model.__name__, fides_key=fides_key):
136
+ try:
137
+ log.debug("Fetching resource")
138
+ query = select(sql_model).where(sql_model.fides_key == fides_key)
139
+ result = await async_session.execute(query)
140
+ except SQLAlchemyError as e:
141
+ sa_error = errors.QueryError()
142
+ log.exception(f"Failed to fetch resource with error: '{e}'")
143
+ raise sa_error
144
+
145
+ sql_resource = result.scalars().first()
146
+ if sql_resource is None and raise_not_found:
147
+ not_found_error = errors.NotFoundError(sql_model.__name__, fides_key)
148
+ log.bind(error=not_found_error.detail["error"]).info("Resource not found") # type: ignore[index]
149
+ raise not_found_error
150
+
151
+ return sql_resource
152
+
153
+
154
+ async def get_resource_with_custom_fields(
155
+ sql_model: Type[T], fides_key: str, async_session: AsyncSession
156
+ ) -> Dict[str, Any]:
157
+ """Get a resource from the database by its FidesKey including it's custom fields.
158
+
159
+ Returns a dictionary of that resource.
160
+
161
+ This version does NOT manually manage transactions - transaction management
162
+ is left to the calling code.
163
+ """
164
+ resource: T = await get_resource(sql_model, fides_key, async_session)
165
+ resource_dict = resource.__dict__
166
+ resource_dict.pop("_sa_instance_state", None)
167
+
168
+ with log.contextualize(sql_model=sql_model.__name__, fides_key=fides_key):
169
+ try:
170
+ log.debug("Fetching custom fields for resource")
171
+ query = (
172
+ select(CustomFieldDefinition.name, CustomField.value)
173
+ .join(
174
+ CustomField,
175
+ CustomField.custom_field_definition_id == CustomFieldDefinition.id,
176
+ )
177
+ .where(
178
+ (CustomField.resource_id == resource.fides_key)
179
+ & ( # pylint: disable=singleton-comparison
180
+ CustomFieldDefinition.active == True
181
+ )
182
+ )
183
+ )
184
+ result = await async_session.execute(query)
185
+ except SQLAlchemyError as e:
186
+ sa_error = errors.QueryError()
187
+ log.exception(f"Failed to fetch custom fields with error: '{e}'")
188
+ raise sa_error
189
+
190
+ custom_fields = result.mappings().all()
191
+
192
+ if not custom_fields:
193
+ return resource_dict
194
+
195
+ for field in custom_fields:
196
+ if field["name"] in resource_dict:
197
+ resource_dict[field["name"]] = (
198
+ f"{resource_dict[field['name']]}, {', '.join(field['value'])}"
199
+ )
200
+ else:
201
+ resource_dict[field["name"]] = ", ".join(field["value"])
202
+
203
+ return resource_dict
204
+
205
+
206
+ async def list_resource(sql_model: Type[T], async_session: AsyncSession) -> List[T]:
207
+ """
208
+ Get a list of all of the resources of this type from the database.
209
+
210
+ Returns a list of SQLAlchemy models of that resource type.
211
+
212
+ This version does NOT manually manage transactions - transaction management
213
+ is left to the calling code.
214
+ """
215
+ query = select(sql_model)
216
+ return await list_resource_query(async_session, query, sql_model)
217
+
218
+
219
+ async def list_resource_query(
220
+ async_session: AsyncSession, query: Select, sql_model: Type[T]
221
+ ) -> List[T]:
222
+ """
223
+ Utility function to wrap a select query in generic "list_resource" execution handling.
224
+ Wrapping includes execution against the DB session, logging and error handling.
225
+
226
+ This version does NOT manually manage transactions - transaction management
227
+ is left to the calling code.
228
+ """
229
+
230
+ with log.contextualize(sql_model=sql_model.__name__):
231
+ try:
232
+ log.debug("Fetching resources")
233
+ result = await async_session.execute(query)
234
+ sql_resources = result.scalars().all()
235
+ except SQLAlchemyError as e:
236
+ log.exception(f"Failed to fetch resources with error: '{e}'")
237
+ sa_error = errors.QueryError()
238
+ raise sa_error
239
+
240
+ return sql_resources
241
+
242
+
243
+ async def update_resource(
244
+ sql_model: Type[T], resource_dict: Dict, async_session: AsyncSession
245
+ ) -> Dict:
246
+ """
247
+ Update a resource in the database by its fides_key.
248
+
249
+ This version does NOT manually manage transactions - transaction management
250
+ is left to the calling code.
251
+ """
252
+
253
+ with log.contextualize(
254
+ sql_model=sql_model.__name__, fides_key=resource_dict["fides_key"]
255
+ ):
256
+ await get_resource(sql_model, resource_dict["fides_key"], async_session)
257
+
258
+ try:
259
+ log.debug("Updating resource")
260
+ await async_session.execute(
261
+ _update(sql_model.__table__)
262
+ .where(sql_model.fides_key == resource_dict["fides_key"])
263
+ .values(resource_dict)
264
+ )
265
+ except SQLAlchemyError as e:
266
+ log.exception(f"Failed to update resource with error: '{e}'")
267
+ sa_error = errors.QueryError()
268
+ raise sa_error
269
+
270
+ return await get_resource(sql_model, resource_dict["fides_key"], async_session)
271
+
272
+
273
+ async def upsert_resources(
274
+ sql_model: Type[T], resource_dicts: List[Dict], async_session: AsyncSession
275
+ ) -> Tuple[int, int]:
276
+ """
277
+ Insert new resources into the database. If a resource already exists,
278
+ update it by it's fides_key.
279
+
280
+ Returns a Tuple containing the counts of inserted and updated rows.
281
+
282
+ This version does NOT manually manage transactions - transaction management
283
+ is left to the calling code.
284
+ """
285
+
286
+ with log.contextualize(
287
+ sql_model=sql_model.__name__,
288
+ fides_keys=[resource["fides_key"] for resource in resource_dicts],
289
+ ):
290
+ try:
291
+ log.debug("Upserting resources")
292
+ insert_stmt = (
293
+ _insert(sql_model.__table__)
294
+ .values(resource_dicts)
295
+ .returning(
296
+ (column("xmax") == 0), # Row was inserted
297
+ (column("xmax") != 0), # Row was updated
298
+ )
299
+ )
300
+
301
+ excluded = dict(insert_stmt.excluded.items()) # type: ignore[attr-defined]
302
+ excluded.pop("id", None) # If updating, don't update the "id"
303
+
304
+ result = await async_session.execute(
305
+ insert_stmt.on_conflict_do_update(
306
+ index_elements=["fides_key"],
307
+ set_=excluded,
308
+ )
309
+ )
310
+
311
+ inserts, updates = 0, 0
312
+ for xmax in result:
313
+ inserts += 1 if xmax[0] else 0
314
+ updates += 1 if xmax[1] else 0
315
+
316
+ return (inserts, updates)
317
+
318
+ except SQLAlchemyError as e:
319
+ log.exception(f"Failed to upsert resources with error: '{e}'")
320
+ sa_error = errors.QueryError()
321
+ raise sa_error
322
+
323
+
324
+ async def delete_resource(
325
+ sql_model: Type[T], fides_key: str, async_session: AsyncSession
326
+ ) -> T:
327
+ """
328
+ Delete a resource by its fides_key.
329
+
330
+ If the resource has child keys referring to it, also delete those.
331
+
332
+ This version does NOT manually manage transactions - transaction management
333
+ is left to the calling code.
334
+ """
335
+
336
+ with log.contextualize(sql_model=sql_model.__name__, fides_key=fides_key):
337
+ sql_resource = await get_resource(sql_model, fides_key, async_session)
338
+
339
+ try:
340
+ # Automatically delete related resources if they are CTL objects
341
+ if hasattr(sql_model, "parent_key"):
342
+ log.debug("Deleting resource and its children")
343
+ query = (
344
+ _delete(sql_model.__table__)
345
+ .where(
346
+ or_(
347
+ sql_model.fides_key == fides_key,
348
+ sql_model.fides_key.like(f"{fides_key}.%"),
349
+ )
350
+ )
351
+ .execution_options(synchronize_session=False)
352
+ )
353
+ else:
354
+ log.debug("Deleting resource")
355
+ query = _delete(sql_model.__table__).where(
356
+ sql_model.fides_key == fides_key
357
+ )
358
+ await async_session.execute(query)
359
+ except IntegrityError as err:
360
+ raw_error_text: str = err.orig.args[0]
361
+
362
+ if "violates foreign key constraint" in raw_error_text:
363
+ error_message = "Failed to delete resource! Foreign key constraint found, try deleting related resources first."
364
+ else:
365
+ error_message = "Failed to delete resource!"
366
+
367
+ log.bind(error="SQL Query integrity error!").error(raw_error_text)
368
+ raise HTTPException(
369
+ status_code=HTTP_422_UNPROCESSABLE_ENTITY,
370
+ detail=error_message,
371
+ )
372
+ except SQLAlchemyError as e:
373
+ log.exception(f"Failed to delete resource with error: '{e}'")
374
+ sa_error = errors.QueryError()
375
+ raise sa_error
376
+
377
+ return sql_resource
@@ -177,6 +177,30 @@ class Policy(Base):
177
177
  for category in node.get_data_categories()
178
178
  )
179
179
 
180
+ def to_safe_dict(self) -> Dict[str, Any]:
181
+ """
182
+ Returns a dictionary representation of the Policy, excluding sensitive information.
183
+ """
184
+ return {
185
+ "id": self.id,
186
+ "name": self.name,
187
+ "key": self.key,
188
+ "drp_action": self.drp_action.value if self.drp_action else None, # type: ignore[attr-defined]
189
+ "execution_timeframe": self.execution_timeframe,
190
+ "client_id": self.client_id,
191
+ "rules": [
192
+ {
193
+ "id": rule.id,
194
+ "name": rule.name,
195
+ "key": rule.key,
196
+ "action_type": rule.action_type.value,
197
+ "masking_strategy": rule.masking_strategy,
198
+ "storage_destination_id": rule.storage_destination_id,
199
+ }
200
+ for rule in self.rules # type: ignore[attr-defined]
201
+ ],
202
+ }
203
+
180
204
 
181
205
  def _get_ref_from_taxonomy(
182
206
  fides_key: FidesKey,
@@ -41,7 +41,7 @@ class UserConsentPreference(Enum):
41
41
  tcf = "tcf" # Overall preference set for TCF where there are numerous preferences under the single notice
42
42
 
43
43
 
44
- class ConsentMechanism(Enum):
44
+ class ConsentMechanism(str, Enum):
45
45
  """
46
46
  Enum is not formalized in the DB because it may be subject to frequent change
47
47
  """
@@ -355,6 +355,64 @@ class PrivacyRequest(
355
355
 
356
356
  return super().create(db=db, data=data, check_name=check_name)
357
357
 
358
+ def to_safe_dict(self) -> Dict[str, Any]:
359
+ """
360
+ Return a dict representation of the PrivacyRequest, excluding any fields
361
+ that may contain sensitive information.
362
+ """
363
+ return {
364
+ "id": self.id,
365
+ "external_id": self.external_id,
366
+ "status": self.status.value,
367
+ "requested_at": (
368
+ self.requested_at.isoformat() if self.requested_at else None
369
+ ),
370
+ "started_processing_at": (
371
+ self.started_processing_at.isoformat()
372
+ if self.started_processing_at
373
+ else None
374
+ ),
375
+ "finished_processing_at": (
376
+ self.finished_processing_at.isoformat()
377
+ if self.finished_processing_at
378
+ else None
379
+ ),
380
+ "reviewed_at": self.reviewed_at.isoformat() if self.reviewed_at else None,
381
+ "reviewed_by": self.reviewed_by,
382
+ "finalized_at": (
383
+ self.finalized_at.isoformat() if self.finalized_at else None
384
+ ),
385
+ "finalized_by": self.finalized_by,
386
+ "submitted_by": self.submitted_by,
387
+ "custom_privacy_request_fields_approved_by": (
388
+ self.custom_privacy_request_fields_approved_by
389
+ ),
390
+ "identity_verified_at": (
391
+ self.identity_verified_at.isoformat()
392
+ if self.identity_verified_at
393
+ else None
394
+ ),
395
+ "custom_privacy_request_fields_approved_at": (
396
+ self.custom_privacy_request_fields_approved_at.isoformat()
397
+ if self.custom_privacy_request_fields_approved_at
398
+ else None
399
+ ),
400
+ "client_id": self.client_id,
401
+ "origin": self.origin,
402
+ "policy_id": self.policy_id,
403
+ "policy": self.policy.to_safe_dict() if self.policy else None,
404
+ "property_id": self.property_id,
405
+ "cancel_reason": self.cancel_reason,
406
+ "canceled_at": self.canceled_at.isoformat() if self.canceled_at else None,
407
+ "consent_preferences": self.consent_preferences,
408
+ "source": self.source.value if self.source else None,
409
+ "paused_at": self.paused_at.isoformat() if self.paused_at else None,
410
+ "due_date": self.due_date.isoformat() if self.due_date else None,
411
+ "days_left": self.days_left,
412
+ "custom_fields": self.get_persisted_custom_privacy_request_fields() if self.custom_fields else None, # type: ignore[attr-defined]
413
+ "location": self.location,
414
+ }
415
+
358
416
  def clear_cached_values(self) -> None:
359
417
  """
360
418
  Clears all cached values associated with this privacy request from Redis.
@@ -903,6 +961,8 @@ class PrivacyRequest(
903
961
  callback_type=CallbackType.pre_approval,
904
962
  identity=self.get_cached_identity_data(),
905
963
  policy_action=policy_action,
964
+ privacy_request=self.to_safe_dict(),
965
+ timestamp=datetime.utcnow(),
906
966
  )
907
967
  headers = {
908
968
  "reply-to-approve": f"/privacy-request/{self.id}/pre-approve/eligible",
@@ -943,6 +1003,8 @@ class PrivacyRequest(
943
1003
  callback_type=webhook.prefix,
944
1004
  identity=self.get_cached_identity_data(),
945
1005
  policy_action=policy_action,
1006
+ privacy_request=self.to_safe_dict(),
1007
+ timestamp=datetime.utcnow(),
946
1008
  )
947
1009
 
948
1010
  headers = {}
@@ -5,7 +5,7 @@ from __future__ import annotations
5
5
  import json
6
6
  from datetime import datetime
7
7
  from enum import Enum as EnumType
8
- from typing import Optional
8
+ from typing import Any, Dict, Optional
9
9
 
10
10
  from pydantic import BaseModel, ConfigDict
11
11
 
@@ -51,6 +51,8 @@ class SecondPartyRequestFormat(BaseModel):
51
51
  identity: Identity
52
52
  policy_action: Optional[ActionType] = None
53
53
  model_config = ConfigDict(use_enum_values=True)
54
+ privacy_request: Dict[str, Any]
55
+ timestamp: datetime
54
56
 
55
57
 
56
58
  def generate_request_callback_resume_jwe(webhook: PolicyPreWebhook) -> str:
@@ -1,4 +1,4 @@
1
- from typing import ClassVar, List
1
+ from typing import ClassVar, List, Optional
2
2
 
3
3
  from pydantic import Field
4
4
 
@@ -30,10 +30,22 @@ class MongoDBSchema(ConnectionConfigSecretsSchema):
30
30
  json_schema_extra={"sensitive": True},
31
31
  )
32
32
  defaultauthdb: str = Field(
33
- title="Default Auth DB",
33
+ title="Default auth DB",
34
34
  description="Used to specify the default authentication database.",
35
35
  )
36
36
 
37
+ use_srv: Optional[bool] = Field(
38
+ False,
39
+ title="Use SRV",
40
+ description="Enable SRV record lookup for service discovery (mongodb+srv://). Required for MongoDB Atlas. Enables SSL by default.",
41
+ )
42
+
43
+ ssl_enabled: Optional[bool] = Field(
44
+ None,
45
+ title="SSL enabled",
46
+ description="Enable SSL/TLS encryption. With SRV: defaults to enabled (can override). Without SRV: defaults to disabled.",
47
+ )
48
+
37
49
  _required_components: ClassVar[List[str]] = [
38
50
  "host",
39
51
  "username",