ethyca-fides 2.70.3rc0__py2.py3-none-any.whl → 2.70.4b0__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 (207) hide show
  1. {ethyca_fides-2.70.3rc0.dist-info → ethyca_fides-2.70.4b0.dist-info}/METADATA +3 -3
  2. {ethyca_fides-2.70.3rc0.dist-info → ethyca_fides-2.70.4b0.dist-info}/RECORD +205 -199
  3. fides/_version.py +3 -3
  4. fides/api/alembic/migrations/versions/a8e0c016afd_add_classification_benchmark_table.py +126 -0
  5. fides/api/alembic/migrations/versions/cd8649be3a2b_add_classifications_and_user_assigned_.py +74 -0
  6. fides/api/db/crud.py +30 -2
  7. fides/api/db/database.py +1 -1
  8. fides/api/db/safe_crud.py +377 -0
  9. fides/api/migrations/post_upgrade_index_creation.py +10 -0
  10. fides/api/models/conditional_dependency/__init__.py +0 -0
  11. fides/api/models/conditional_dependency/conditional_dependency_base.py +82 -0
  12. fides/api/models/detection_discovery/__init__.py +2 -0
  13. fides/api/models/detection_discovery/classification_benchmark.py +140 -0
  14. fides/api/models/detection_discovery/core.py +11 -0
  15. fides/api/models/manual_task/conditional_dependency.py +21 -77
  16. fides/api/models/policy.py +24 -0
  17. fides/api/models/privacy_notice.py +1 -1
  18. fides/api/models/privacy_request/privacy_request.py +68 -0
  19. fides/api/models/privacy_request/webhook.py +3 -1
  20. fides/api/oauth/roles.py +2 -0
  21. fides/api/schemas/privacy_request.py +4 -2
  22. fides/api/schemas/user.py +2 -2
  23. fides/api/service/privacy_request/dsr_package/dsr_report_builder.py +2 -2
  24. fides/api/service/storage/streaming/smart_open_streaming_storage.py +36 -28
  25. fides/api/service/storage/util.py +11 -102
  26. fides/api/task/manual/manual_task_utils.py +5 -6
  27. fides/ui-build/static/admin/404.html +1 -1
  28. fides/ui-build/static/admin/_next/static/chunks/155-047c3806cc41295e.js +1 -0
  29. fides/ui-build/static/admin/_next/static/chunks/{7476-0b6e114658b15eaa.js → 7476-d055aa931da47ac0.js} +1 -1
  30. fides/ui-build/static/admin/_next/static/chunks/{7725-dd6736855807936a.js → 7725-fdc4298dfbea6f80.js} +1 -1
  31. fides/ui-build/static/admin/_next/static/chunks/pages/{_app-a4e3c999afb28ee7.js → _app-de41f80e35acbde0.js} +1 -1
  32. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-3d03cd31cd99fa07.js +1 -0
  33. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/{[id]-8b13bb5f7bee61c6.js → [id]-9f6c82e14ff2cad2.js} +1 -1
  34. fides/ui-build/static/admin/_next/static/chunks/pages/{integrations-6f109ef64304ef59.js → integrations-ebc9c90fe99ee68d.js} +1 -1
  35. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/{[id]-8566e3b7b2a632fa.js → [id]-f8e3f63bea43db3b.js} +1 -1
  36. fides/ui-build/static/admin/_next/static/{Ti_tN22v2FS5pmVDklKnU → gAyR6aUQCeUTA_oMVYpBp}/_buildManifest.js +1 -1
  37. fides/ui-build/static/admin/add-systems/manual.html +1 -1
  38. fides/ui-build/static/admin/add-systems/multiple.html +1 -1
  39. fides/ui-build/static/admin/add-systems.html +1 -1
  40. fides/ui-build/static/admin/consent/configure/add-vendors.html +1 -1
  41. fides/ui-build/static/admin/consent/configure.html +1 -1
  42. fides/ui-build/static/admin/consent/privacy-experience/[id].html +1 -1
  43. fides/ui-build/static/admin/consent/privacy-experience/new.html +1 -1
  44. fides/ui-build/static/admin/consent/privacy-experience.html +1 -1
  45. fides/ui-build/static/admin/consent/privacy-notices/[id].html +1 -1
  46. fides/ui-build/static/admin/consent/privacy-notices/new.html +1 -1
  47. fides/ui-build/static/admin/consent/privacy-notices.html +1 -1
  48. fides/ui-build/static/admin/consent/properties.html +1 -1
  49. fides/ui-build/static/admin/consent/reporting.html +1 -1
  50. fides/ui-build/static/admin/consent.html +1 -1
  51. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn].html +1 -1
  52. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn].html +1 -1
  53. fides/ui-build/static/admin/data-catalog/[systemId]/projects.html +1 -1
  54. fides/ui-build/static/admin/data-catalog/[systemId]/resources/[resourceUrn].html +1 -1
  55. fides/ui-build/static/admin/data-catalog/[systemId]/resources.html +1 -1
  56. fides/ui-build/static/admin/data-catalog.html +1 -1
  57. fides/ui-build/static/admin/data-discovery/action-center/[monitorId]/[systemId].html +1 -1
  58. fides/ui-build/static/admin/data-discovery/action-center/[monitorId].html +1 -1
  59. fides/ui-build/static/admin/data-discovery/action-center.html +1 -1
  60. fides/ui-build/static/admin/data-discovery/activity.html +1 -1
  61. fides/ui-build/static/admin/data-discovery/detection/[resourceUrn].html +1 -1
  62. fides/ui-build/static/admin/data-discovery/detection.html +1 -1
  63. fides/ui-build/static/admin/data-discovery/discovery/[resourceUrn].html +1 -1
  64. fides/ui-build/static/admin/data-discovery/discovery.html +1 -1
  65. fides/ui-build/static/admin/datamap.html +1 -1
  66. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName]/[...subfieldNames].html +1 -1
  67. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName].html +1 -1
  68. fides/ui-build/static/admin/dataset/[datasetId].html +1 -1
  69. fides/ui-build/static/admin/dataset/new.html +1 -1
  70. fides/ui-build/static/admin/dataset.html +1 -1
  71. fides/ui-build/static/admin/datastore-connection/[id].html +1 -1
  72. fides/ui-build/static/admin/datastore-connection/new.html +1 -1
  73. fides/ui-build/static/admin/datastore-connection.html +1 -1
  74. fides/ui-build/static/admin/index.html +1 -1
  75. fides/ui-build/static/admin/integrations/[id].html +1 -1
  76. fides/ui-build/static/admin/integrations.html +1 -1
  77. fides/ui-build/static/admin/login/[provider].html +1 -1
  78. fides/ui-build/static/admin/login.html +1 -1
  79. fides/ui-build/static/admin/messaging/[id].html +1 -1
  80. fides/ui-build/static/admin/messaging/add-template.html +1 -1
  81. fides/ui-build/static/admin/messaging.html +1 -1
  82. fides/ui-build/static/admin/poc/ant-components.html +1 -1
  83. fides/ui-build/static/admin/poc/form-experiments/AntForm.html +1 -1
  84. fides/ui-build/static/admin/poc/form-experiments/FormikAntFormItem.html +1 -1
  85. fides/ui-build/static/admin/poc/form-experiments/FormikControlled.html +1 -1
  86. fides/ui-build/static/admin/poc/form-experiments/FormikField.html +1 -1
  87. fides/ui-build/static/admin/poc/form-experiments/FormikSpreadField.html +1 -1
  88. fides/ui-build/static/admin/poc/forms.html +1 -1
  89. fides/ui-build/static/admin/poc/table-migration.html +1 -1
  90. fides/ui-build/static/admin/privacy-requests/[id].html +1 -1
  91. fides/ui-build/static/admin/privacy-requests/configure/storage.html +1 -1
  92. fides/ui-build/static/admin/privacy-requests/configure.html +1 -1
  93. fides/ui-build/static/admin/privacy-requests.html +1 -1
  94. fides/ui-build/static/admin/properties/[id].html +1 -1
  95. fides/ui-build/static/admin/properties/add-property.html +1 -1
  96. fides/ui-build/static/admin/properties.html +1 -1
  97. fides/ui-build/static/admin/reporting/datamap.html +1 -1
  98. fides/ui-build/static/admin/settings/about/alpha.html +1 -1
  99. fides/ui-build/static/admin/settings/about.html +1 -1
  100. fides/ui-build/static/admin/settings/consent/[configuration_id]/[purpose_id].html +1 -1
  101. fides/ui-build/static/admin/settings/consent.html +1 -1
  102. fides/ui-build/static/admin/settings/custom-fields.html +1 -1
  103. fides/ui-build/static/admin/settings/domain-records.html +1 -1
  104. fides/ui-build/static/admin/settings/domains.html +1 -1
  105. fides/ui-build/static/admin/settings/email-templates.html +1 -1
  106. fides/ui-build/static/admin/settings/locations.html +1 -1
  107. fides/ui-build/static/admin/settings/messaging-providers/[key].html +1 -1
  108. fides/ui-build/static/admin/settings/messaging-providers/new.html +1 -1
  109. fides/ui-build/static/admin/settings/messaging-providers.html +1 -1
  110. fides/ui-build/static/admin/settings/organization.html +1 -1
  111. fides/ui-build/static/admin/settings/privacy-requests.html +1 -1
  112. fides/ui-build/static/admin/settings/regulations.html +1 -1
  113. fides/ui-build/static/admin/systems/configure/[id]/test-datasets.html +1 -1
  114. fides/ui-build/static/admin/systems/configure/[id].html +1 -1
  115. fides/ui-build/static/admin/systems.html +1 -1
  116. fides/ui-build/static/admin/taxonomy.html +1 -1
  117. fides/ui-build/static/admin/user-management/new.html +1 -1
  118. fides/ui-build/static/admin/user-management/profile/[id].html +1 -1
  119. fides/ui-build/static/admin/user-management.html +1 -1
  120. fides/ui-build/static/admin/_next/static/chunks/155-88303b05c6e115a5.js +0 -1
  121. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-b0e3f1886de28d66.js +0 -1
  122. {ethyca_fides-2.70.3rc0.dist-info → ethyca_fides-2.70.4b0.dist-info}/WHEEL +0 -0
  123. {ethyca_fides-2.70.3rc0.dist-info → ethyca_fides-2.70.4b0.dist-info}/entry_points.txt +0 -0
  124. {ethyca_fides-2.70.3rc0.dist-info → ethyca_fides-2.70.4b0.dist-info}/licenses/LICENSE +0 -0
  125. {ethyca_fides-2.70.3rc0.dist-info → ethyca_fides-2.70.4b0.dist-info}/top_level.txt +0 -0
  126. /fides/ui-build/static/admin/_next/static/chunks/{1115-7888473b3dc28cda.js → 1115-90baef2a89f361ad.js} +0 -0
  127. /fides/ui-build/static/admin/_next/static/chunks/{1817-ee9e29a6b8c4af50.js → 1817-dbde9966025d7970.js} +0 -0
  128. /fides/ui-build/static/admin/_next/static/chunks/{2040-ab6212a3074f34f9.js → 2040-fdecc41a18e40bdc.js} +0 -0
  129. /fides/ui-build/static/admin/_next/static/chunks/{3696-c25dc8d1b0e1aee1.js → 3696-90c8b336bbc46782.js} +0 -0
  130. /fides/ui-build/static/admin/_next/static/chunks/{3700-dc3f05d21e2a5ff6.js → 3700-865408b36fbee782.js} +0 -0
  131. /fides/ui-build/static/admin/_next/static/chunks/{3872-3514b712afd683c0.js → 3872-04d3afbfa41a7782.js} +0 -0
  132. /fides/ui-build/static/admin/_next/static/chunks/{4608-b22905c65f61db15.js → 4608-a9941d0c236ebca1.js} +0 -0
  133. /fides/ui-build/static/admin/_next/static/chunks/{502-a40d39e615f7b664.js → 502-d3ecae97b67befbd.js} +0 -0
  134. /fides/ui-build/static/admin/_next/static/chunks/{5185-33f50cf9ae17b42e.js → 5185-51eaa78e3ed6bfb7.js} +0 -0
  135. /fides/ui-build/static/admin/_next/static/chunks/{5574-b8c4cba5a6938c00.js → 5574-c31ea831371610d5.js} +0 -0
  136. /fides/ui-build/static/admin/_next/static/chunks/{5783-8de76df87af55e98.js → 5783-8f5713517ebc35f3.js} +0 -0
  137. /fides/ui-build/static/admin/_next/static/chunks/{6084-2cd165179c428a6f.js → 6084-dc473a58c3e2889b.js} +0 -0
  138. /fides/ui-build/static/admin/_next/static/chunks/{6416-264aadc6b336ee0a.js → 6416-0ccadfefcdad00cc.js} +0 -0
  139. /fides/ui-build/static/admin/_next/static/chunks/{6882-447f15e87b8c48a5.js → 6882-10296485ec326e6b.js} +0 -0
  140. /fides/ui-build/static/admin/_next/static/chunks/{6954-599f2de2c902e9b2.js → 6954-4b24e1731c1cc3b3.js} +0 -0
  141. /fides/ui-build/static/admin/_next/static/chunks/{7158-835ba42fd881d8dd.js → 7158-04745cc8d684b2e7.js} +0 -0
  142. /fides/ui-build/static/admin/_next/static/chunks/{7630-e7ea13be69c118a1.js → 7630-d0d3a0fe3f95e971.js} +0 -0
  143. /fides/ui-build/static/admin/_next/static/chunks/{796-e07ac2c543f569e3.js → 796-876998c86754da97.js} +0 -0
  144. /fides/ui-build/static/admin/_next/static/chunks/{8002-25fd174aec9b077b.js → 8002-ed832921ad190832.js} +0 -0
  145. /fides/ui-build/static/admin/_next/static/chunks/{9226-2f960b7ca530642a.js → 9226-4a7027057f55ca2a.js} +0 -0
  146. /fides/ui-build/static/admin/_next/static/chunks/{9826-c02be5882205bbbc.js → 9826-ccedc28e978ca9e1.js} +0 -0
  147. /fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{manual-939253f8daf349b2.js → manual-16ecb33f09224fbb.js} +0 -0
  148. /fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{multiple-83ed7da0bb90b0a5.js → multiple-2ca59996860a33c5.js} +0 -0
  149. /fides/ui-build/static/admin/_next/static/chunks/pages/{add-systems-f90aa48500c1cbde.js → add-systems-caff552fce501f82.js} +0 -0
  150. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure/{add-vendors-46b88bda3d7b15c5.js → add-vendors-7a258b7ecd6da4b8.js} +0 -0
  151. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{configure-c0db068d1863222f.js → configure-259ad2e10fe6f413.js} +0 -0
  152. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-experience-92a337ee96845af2.js → privacy-experience-7e78616b7b048978.js} +0 -0
  153. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{[id]-1fd2cda8707314f6.js → [id]-9c23fbe813c997d0.js} +0 -0
  154. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{new-2987e397445713c5.js → new-0e5e38bbcfe59fd2.js} +0 -0
  155. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-notices-59a8aff5935482ec.js → privacy-notices-3ff2fd2570f02f1c.js} +0 -0
  156. /fides/ui-build/static/admin/_next/static/chunks/pages/{consent-e5a33654a2dfaf35.js → consent-d2bf72508c3cad55.js} +0 -0
  157. /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]/{[resourceUrn]-293c1f2d9aefb447.js → [resourceUrn]-06a08970907ed3f0.js} +0 -0
  158. /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/{[projectUrn]-6a4b0d49dcbf17a8.js → [projectUrn]-4a1af12d2d7cd660.js} +0 -0
  159. /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{projects-be7b385073f22414.js → projects-99573a1ee3ef8f4c.js} +0 -0
  160. /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/resources/{[resourceUrn]-18501152fa1e4f40.js → [resourceUrn]-4c84d952bb1db690.js} +0 -0
  161. /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{resources-af80fdca3bbdc82f.js → resources-6e429b7511028d60.js} +0 -0
  162. /fides/ui-build/static/admin/_next/static/chunks/pages/{data-catalog-351caadeef03876a.js → data-catalog-56fd0f3e465e52b6.js} +0 -0
  163. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/{[monitorId]-e8ec4080d9a3e22f.js → [monitorId]-b74dfaf4f4126e57.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/configure/{storage-1b38b656807ed0cd.js → storage-648d775d0fce49dc.js} +0 -0
  184. /fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/{configure-b00532a0ad4f6927.js → configure-8f577df28ebca869.js} +0 -0
  185. /fides/ui-build/static/admin/_next/static/chunks/pages/{privacy-requests-2c82cf73d20416f2.js → privacy-requests-1eeb320867dbebf4.js} +0 -0
  186. /fides/ui-build/static/admin/_next/static/chunks/pages/properties/{[id]-322a01e2bceab3fb.js → [id]-57a75c7e9659271a.js} +0 -0
  187. /fides/ui-build/static/admin/_next/static/chunks/pages/properties/{add-property-777ed2d73812043d.js → add-property-8964c2300206bc89.js} +0 -0
  188. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{consent-55e36839d219a503.js → consent-1ae1257f5b388924.js} +0 -0
  189. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{custom-fields-26ce8fc493993765.js → custom-fields-c2f1376aca192114.js} +0 -0
  190. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domain-records-7ddf9d992fe714a6.js → domain-records-586505df9d853f1f.js} +0 -0
  191. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domains-7c78ae51f0dd7102.js → domains-a3275554ffe8e640.js} +0 -0
  192. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{email-templates-05ffbda19ab894b9.js → email-templates-604790638c656fbd.js} +0 -0
  193. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{locations-77fb85bdd0be42b5.js → locations-be2a885150adc133.js} +0 -0
  194. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/messaging-providers/{[key]-b0d93bf478bf63ee.js → [key]-8df31428446a6a96.js} +0 -0
  195. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/messaging-providers/{new-084f9756b9987285.js → new-af1471bf4571d5d3.js} +0 -0
  196. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{messaging-providers-6c51ffd46bb598e7.js → messaging-providers-8d92be437793c96f.js} +0 -0
  197. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{organization-44456bfe54ac4ad5.js → organization-3c86162afe9759df.js} +0 -0
  198. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{privacy-requests-fbe7e8030d837aed.js → privacy-requests-8cbdfd08e0fa88fb.js} +0 -0
  199. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{regulations-2866ac99faa5a542.js → regulations-4fe3b90747d885e5.js} +0 -0
  200. /fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/{test-datasets-a86bafe1b4e1205f.js → test-datasets-2deb6becece69d46.js} +0 -0
  201. /fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/{[id]-1895c6a13b543436.js → [id]-589952aa1a31c33d.js} +0 -0
  202. /fides/ui-build/static/admin/_next/static/chunks/pages/{systems-d266cc062b56beb2.js → systems-916238dcc0596957.js} +0 -0
  203. /fides/ui-build/static/admin/_next/static/chunks/pages/{taxonomy-07848c232d960f6a.js → taxonomy-616f5a7cbb99e46d.js} +0 -0
  204. /fides/ui-build/static/admin/_next/static/chunks/pages/user-management/{new-6304dad2c5fab694.js → new-629c88e90699369b.js} +0 -0
  205. /fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/{[id]-ff4711db191099cd.js → [id]-98f737e735eaa0f0.js} +0 -0
  206. /fides/ui-build/static/admin/_next/static/chunks/pages/{user-management-82fcf1151e2fe2ba.js → user-management-562624e5461083ec.js} +0 -0
  207. /fides/ui-build/static/admin/_next/static/{Ti_tN22v2FS5pmVDklKnU → gAyR6aUQCeUTA_oMVYpBp}/_ssgManifest.js +0 -0
@@ -1,13 +1,14 @@
1
- from enum import Enum
2
- from typing import TYPE_CHECKING, Optional, Union
1
+ from typing import TYPE_CHECKING, Any, Optional, Union
3
2
 
4
- from sqlalchemy import Column, ForeignKey, Index, Integer, String
5
- from sqlalchemy.dialects.postgresql import JSONB
3
+ from sqlalchemy import Column, ForeignKey, Index, String
6
4
  from sqlalchemy.ext.declarative import declared_attr
7
5
  from sqlalchemy.orm import Session, relationship
8
6
 
9
- from fides.api.db.base_class import Base, FidesBase
10
- from fides.api.db.util import EnumColumn
7
+ from fides.api.db.base_class import FidesBase
8
+ from fides.api.models.conditional_dependency.conditional_dependency_base import (
9
+ ConditionalDependencyBase,
10
+ ConditionalDependencyType,
11
+ )
11
12
  from fides.api.task.conditional_dependencies.schemas import (
12
13
  ConditionGroup,
13
14
  ConditionLeaf,
@@ -17,42 +18,16 @@ if TYPE_CHECKING:
17
18
  from fides.api.models.manual_task.manual_task import ManualTask
18
19
 
19
20
 
20
- class ManualTaskConditionalDependencyType(str, Enum):
21
- """Enum for manual task conditional dependency types.
22
-
23
- This enum defines the two types of nodes in a conditional dependency tree:
24
-
25
- - leaf: A terminal node that represents a single condition (e.g., "user.age >= 18")
26
- - group: A non-terminal node that groups multiple conditions with logical operators (AND/OR)
27
-
28
- Examples:
29
- leaf: Used for simple field comparisons like:
30
- - "user.name exists"
31
- - "user.age >= 18"
32
- - "billing.subscription.status == 'active'"
33
-
34
- group: Used to combine multiple conditions with logical operators:
35
- - AND group: "user.age >= 18 AND user.active == true"
36
- - OR group: "user.role == 'admin' OR user.verified == true"
37
- - Nested groups: "(user.age >= 18 AND (user.role == 'admin' OR user.verified == true))"
38
- """
39
-
40
- leaf = "leaf"
41
- group = "group"
42
-
43
-
44
- class ManualTaskConditionalDependency(Base):
45
- """Model for storing conditional dependencies."""
21
+ class ManualTaskConditionalDependency(ConditionalDependencyBase):
22
+ """Manual task conditional dependencies - single type hierarchy."""
46
23
 
47
24
  @declared_attr
48
25
  def __tablename__(cls) -> str:
49
- """Overriding base class method to set the table name."""
50
26
  return "manual_task_conditional_dependency"
51
27
 
52
28
  # We need to redefine it here so that self-referential relationships
53
29
  # can properly reference the `id` column instead of the built-in Python function.
54
30
  id = Column(String(255), primary_key=True, default=FidesBase.generate_uuid)
55
-
56
31
  # Foreign key relationships
57
32
  manual_task_id = Column(
58
33
  String, ForeignKey("manual_task.id", ondelete="CASCADE"), nullable=False
@@ -63,18 +38,6 @@ class ManualTaskConditionalDependency(Base):
63
38
  nullable=True,
64
39
  )
65
40
 
66
- # Condition metadata
67
- condition_type = Column(
68
- EnumColumn(ManualTaskConditionalDependencyType), nullable=False
69
- ) # leaf or group
70
- field_address = Column(String, nullable=True) # For leaf conditions
71
- operator = Column(String, nullable=True) # For leaf conditions
72
- value = Column(JSONB, nullable=True) # For leaf conditions
73
- logical_operator = Column(String, nullable=True) # 'and' or 'or' for groups
74
-
75
- # Ordering
76
- sort_order = Column(Integer, nullable=False, default=0)
77
-
78
41
  __table_args__ = (
79
42
  Index("ix_manual_task_conditional_dependency_manual_task_id", "manual_task_id"),
80
43
  Index("ix_manual_task_conditional_dependency_parent_id", "parent_id"),
@@ -97,38 +60,20 @@ class ManualTaskConditionalDependency(Base):
97
60
  foreign_keys=[parent_id],
98
61
  )
99
62
 
100
- def to_condition_leaf(self) -> ConditionLeaf:
101
- """Convert to ConditionLeaf if this is a leaf condition"""
102
- if self.condition_type != "leaf":
103
- raise ValueError("Cannot convert group condition to leaf")
104
-
105
- return ConditionLeaf(
106
- field_address=self.field_address, operator=self.operator, value=self.value
107
- )
108
-
109
- def to_condition_group(self) -> ConditionGroup:
110
- """Convert to ConditionGroup if this is a group condition"""
111
- if self.condition_type != "group":
112
- raise ValueError("Cannot convert leaf condition to group")
113
-
114
- # Recursively build children
115
- child_conditions = []
116
- children_list = [child for child in self.children] # type: ignore[attr-defined]
117
- for child in sorted(children_list, key=lambda x: x.sort_order):
118
- if child.condition_type == "leaf":
119
- child_conditions.append(child.to_condition_leaf())
120
- else:
121
- child_conditions.append(child.to_condition_group())
122
-
123
- return ConditionGroup(
124
- logical_operator=self.logical_operator, conditions=child_conditions
125
- )
126
-
127
63
  @classmethod
128
64
  def get_root_condition(
129
- cls, db: Session, manual_task_id: str
65
+ cls, db: Session, *args: Any, **kwargs: Any
130
66
  ) -> Optional[Union[ConditionLeaf, ConditionGroup]]:
131
- """Get the root condition for a config"""
67
+ """Get the root condition for a manual task
68
+
69
+ Args:
70
+ db: Database session
71
+ manual_task_id: ID of the manual task (first positional arg)
72
+ """
73
+ if not args:
74
+ raise ValueError("manual_task_id is required as first positional argument")
75
+
76
+ manual_task_id = args[0]
132
77
  root = (
133
78
  db.query(cls)
134
79
  .filter(cls.manual_task_id == manual_task_id, cls.parent_id.is_(None))
@@ -138,7 +83,6 @@ class ManualTaskConditionalDependency(Base):
138
83
  if not root:
139
84
  return None
140
85
 
141
- if root.condition_type == "leaf":
86
+ if root.condition_type == ConditionalDependencyType.leaf:
142
87
  return root.to_condition_leaf()
143
-
144
88
  return root.to_condition_group()
@@ -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
  """
@@ -261,6 +261,12 @@ class PrivacyRequest(
261
261
  foreign_keys=[reviewed_by],
262
262
  )
263
263
 
264
+ submitter = relationship(
265
+ FidesUser,
266
+ backref=backref("submitted_privacy_requests", passive_deletes=True),
267
+ foreign_keys=[submitted_by],
268
+ )
269
+
264
270
  pre_approval_webhook_replies = relationship(
265
271
  PreApprovalWebhookReply,
266
272
  back_populates="privacy_request",
@@ -355,6 +361,64 @@ class PrivacyRequest(
355
361
 
356
362
  return super().create(db=db, data=data, check_name=check_name)
357
363
 
364
+ def to_safe_dict(self) -> Dict[str, Any]:
365
+ """
366
+ Return a dict representation of the PrivacyRequest, excluding any fields
367
+ that may contain sensitive information.
368
+ """
369
+ return {
370
+ "id": self.id,
371
+ "external_id": self.external_id,
372
+ "status": self.status.value,
373
+ "requested_at": (
374
+ self.requested_at.isoformat() if self.requested_at else None
375
+ ),
376
+ "started_processing_at": (
377
+ self.started_processing_at.isoformat()
378
+ if self.started_processing_at
379
+ else None
380
+ ),
381
+ "finished_processing_at": (
382
+ self.finished_processing_at.isoformat()
383
+ if self.finished_processing_at
384
+ else None
385
+ ),
386
+ "reviewed_at": self.reviewed_at.isoformat() if self.reviewed_at else None,
387
+ "reviewed_by": self.reviewed_by,
388
+ "finalized_at": (
389
+ self.finalized_at.isoformat() if self.finalized_at else None
390
+ ),
391
+ "finalized_by": self.finalized_by,
392
+ "submitted_by": self.submitted_by,
393
+ "custom_privacy_request_fields_approved_by": (
394
+ self.custom_privacy_request_fields_approved_by
395
+ ),
396
+ "identity_verified_at": (
397
+ self.identity_verified_at.isoformat()
398
+ if self.identity_verified_at
399
+ else None
400
+ ),
401
+ "custom_privacy_request_fields_approved_at": (
402
+ self.custom_privacy_request_fields_approved_at.isoformat()
403
+ if self.custom_privacy_request_fields_approved_at
404
+ else None
405
+ ),
406
+ "client_id": self.client_id,
407
+ "origin": self.origin,
408
+ "policy_id": self.policy_id,
409
+ "policy": self.policy.to_safe_dict() if self.policy else None,
410
+ "property_id": self.property_id,
411
+ "cancel_reason": self.cancel_reason,
412
+ "canceled_at": self.canceled_at.isoformat() if self.canceled_at else None,
413
+ "consent_preferences": self.consent_preferences,
414
+ "source": self.source.value if self.source else None,
415
+ "paused_at": self.paused_at.isoformat() if self.paused_at else None,
416
+ "due_date": self.due_date.isoformat() if self.due_date else None,
417
+ "days_left": self.days_left,
418
+ "custom_fields": self.get_persisted_custom_privacy_request_fields() if self.custom_fields else None, # type: ignore[attr-defined]
419
+ "location": self.location,
420
+ }
421
+
358
422
  def clear_cached_values(self) -> None:
359
423
  """
360
424
  Clears all cached values associated with this privacy request from Redis.
@@ -903,6 +967,8 @@ class PrivacyRequest(
903
967
  callback_type=CallbackType.pre_approval,
904
968
  identity=self.get_cached_identity_data(),
905
969
  policy_action=policy_action,
970
+ privacy_request=self.to_safe_dict(),
971
+ timestamp=datetime.utcnow(),
906
972
  )
907
973
  headers = {
908
974
  "reply-to-approve": f"/privacy-request/{self.id}/pre-approve/eligible",
@@ -943,6 +1009,8 @@ class PrivacyRequest(
943
1009
  callback_type=webhook.prefix,
944
1010
  identity=self.get_cached_identity_data(),
945
1011
  policy_action=policy_action,
1012
+ privacy_request=self.to_safe_dict(),
1013
+ timestamp=datetime.utcnow(),
946
1014
  )
947
1015
 
948
1016
  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:
fides/api/oauth/roles.py CHANGED
@@ -26,6 +26,7 @@ from fides.common.api.scope_registry import (
26
26
  PRIVACY_EXPERIENCE_READ,
27
27
  PRIVACY_NOTICE_READ,
28
28
  PRIVACY_REQUEST_CALLBACK_RESUME,
29
+ PRIVACY_REQUEST_CREATE,
29
30
  PRIVACY_REQUEST_DELETE,
30
31
  PRIVACY_REQUEST_EMAIL_INTEGRATIONS_SEND,
31
32
  PRIVACY_REQUEST_MANUAL_STEPS_RESPOND,
@@ -88,6 +89,7 @@ approver_scopes = [
88
89
  PRIVACY_REQUEST_UPLOAD_DATA,
89
90
  PRIVACY_REQUEST_VIEW_DATA,
90
91
  PRIVACY_REQUEST_DELETE,
92
+ PRIVACY_REQUEST_CREATE, # allows approvers to create new privacy requests
91
93
  USER_READ, # allows approver to view user management table and update their own password
92
94
  PRIVACY_REQUEST_MANUAL_STEPS_REVIEW, # allows approvers to see all manual steps
93
95
  ]
@@ -14,7 +14,7 @@ from fides.api.schemas.base_class import FidesSchema
14
14
  from fides.api.schemas.policy import ActionType, CurrentStep
15
15
  from fides.api.schemas.policy import PolicyResponse as PolicySchema
16
16
  from fides.api.schemas.redis_cache import CustomPrivacyRequestField, Identity
17
- from fides.api.schemas.user import PrivacyRequestReviewer
17
+ from fides.api.schemas.user import PrivacyRequestUser
18
18
  from fides.api.util.collection_util import Row
19
19
  from fides.api.util.encryption.aes_gcm_encryption_scheme import verify_encryption_key
20
20
  from fides.api.util.enums import ColumnSort
@@ -316,7 +316,9 @@ class PrivacyRequestResponse(FidesSchema):
316
316
  started_processing_at: Optional[datetime] = None
317
317
  reviewed_at: Optional[datetime] = None
318
318
  reviewed_by: Optional[str] = None
319
- reviewer: Optional[PrivacyRequestReviewer] = None
319
+ submitted_by: Optional[str] = None
320
+ reviewer: Optional[PrivacyRequestUser] = None
321
+ submitter: Optional[PrivacyRequestUser] = None
320
322
  finished_processing_at: Optional[datetime] = None
321
323
  identity_verified_at: Optional[datetime] = None
322
324
  paused_at: Optional[datetime] = None
fides/api/schemas/user.py CHANGED
@@ -10,8 +10,8 @@ from fides.api.schemas.base_class import FidesSchema
10
10
  from fides.api.schemas.oauth import AccessToken
11
11
 
12
12
 
13
- class PrivacyRequestReviewer(FidesSchema):
14
- """Data we can expose via the PrivacyRequest.reviewer relation"""
13
+ class PrivacyRequestUser(FidesSchema):
14
+ """Data we can expose via PrivacyRequest user relations (reviewer, submitter, etc.)"""
15
15
 
16
16
  id: str
17
17
  username: str
@@ -26,7 +26,7 @@ from fides.api.service.storage.util import (
26
26
  is_attachment_field,
27
27
  process_attachment_naming,
28
28
  process_attachments_contextually,
29
- resolve_directory_from_context,
29
+ resolve_path_from_context,
30
30
  )
31
31
  from fides.api.util.storage_util import StorageJSONEncoder, format_size
32
32
  from fides.config import CONFIG
@@ -226,7 +226,7 @@ class DSRReportBuilder:
226
226
  file_size = format_attachment_size(attachment.get("file_size"))
227
227
 
228
228
  # Determine the actual directory for this attachment based on its context
229
- actual_directory = resolve_directory_from_context(attachment, directory)
229
+ actual_directory = resolve_path_from_context(attachment, directory)
230
230
 
231
231
  # Generate attachment URL using shared utility with actual storage path
232
232
  download_url = attachment.get("download_url")
@@ -4,6 +4,7 @@ from __future__ import annotations
4
4
  import csv
5
5
  import json
6
6
  import time
7
+ from copy import deepcopy
7
8
  from datetime import datetime
8
9
  from io import BytesIO, StringIO
9
10
  from itertools import chain
@@ -36,13 +37,11 @@ from fides.api.service.storage.streaming.schemas import (
36
37
  )
37
38
  from fides.api.service.storage.streaming.smart_open_client import SmartOpenStorageClient
38
39
  from fides.api.service.storage.util import (
39
- convert_processed_attachments_to_attachment_processing_info,
40
40
  determine_dataset_name_from_path,
41
- extract_storage_key_from_attachment,
42
41
  get_unique_filename,
43
42
  process_attachments_contextually,
44
43
  resolve_attachment_storage_path,
45
- resolve_base_path_from_context,
44
+ resolve_path_from_context,
46
45
  )
47
46
 
48
47
  DEFAULT_ATTACHMENT_NAME = "attachment"
@@ -169,7 +168,9 @@ class SmartOpenStreamingStorage:
169
168
  """
170
169
  try:
171
170
  # Extract storage key using shared utility
172
- storage_key = extract_storage_key_from_attachment(attachment)
171
+ storage_key = (
172
+ attachment.get("download_url") or attachment.get("file_name") or ""
173
+ )
173
174
  if not storage_key:
174
175
  return None
175
176
 
@@ -182,7 +183,7 @@ class SmartOpenStreamingStorage:
182
183
  )
183
184
 
184
185
  # Resolve base path using shared utility
185
- base_path = resolve_base_path_from_context(attachment)
186
+ base_path = resolve_path_from_context(attachment)
186
187
 
187
188
  # Create AttachmentProcessingInfo
188
189
  processing_info = AttachmentProcessingInfo(
@@ -281,7 +282,11 @@ class SmartOpenStreamingStorage:
281
282
  ) from e
282
283
 
283
284
  def _collect_and_validate_attachments(
284
- self, data: dict
285
+ self,
286
+ data: dict,
287
+ used_filenames_data: set[str],
288
+ used_filenames_attachments: set[str],
289
+ processed_attachments: dict[tuple[str, str], str],
285
290
  ) -> list[AttachmentProcessingInfo]:
286
291
  """Collect and validate attachments using the same contextual approach as DSR report builder.
287
292
 
@@ -294,26 +299,30 @@ class SmartOpenStreamingStorage:
294
299
  Returns:
295
300
  List of validated AttachmentProcessingInfo objects
296
301
  """
297
- # Initialize tracking structures (similar to DSR report builder)
298
- used_filenames_data: set[str] = set()
299
- used_filenames_attachments: set[str] = set()
300
- processed_attachments: dict[tuple[str, str], str] = {}
302
+ validated_attachments = []
301
303
 
302
304
  # Use the shared contextual processing function
303
305
  # Note: This method should only be used when DSR report builder is not available
304
306
  # For HTML format, use _collect_and_validate_attachments_from_dsr_builder instead
305
307
  processed_attachments_list = process_attachments_contextually(
306
- data,
307
- used_filenames_data,
308
- used_filenames_attachments,
309
- processed_attachments,
310
- enable_streaming=True, # Always use streaming mode for storage
308
+ data=data,
309
+ used_filenames_data=used_filenames_data,
310
+ used_filenames_attachments=used_filenames_attachments,
311
+ processed_attachments=processed_attachments,
312
+ enable_streaming=True,
311
313
  )
312
314
 
313
- # Convert to AttachmentProcessingInfo objects using shared utility
314
- return convert_processed_attachments_to_attachment_processing_info(
315
- processed_attachments_list, self._validate_attachment
316
- )
315
+ for processed_attachment in processed_attachments_list:
316
+ # Add context information to the attachment data
317
+ attachment_with_context = deepcopy(processed_attachment["attachment"])
318
+ attachment_with_context["_context"] = processed_attachment["context"]
319
+
320
+ # Validate and convert to AttachmentProcessingInfo
321
+ validated = self._validate_attachment(attachment_with_context)
322
+ if validated:
323
+ validated_attachments.append(validated)
324
+
325
+ return validated_attachments
317
326
 
318
327
  def _collect_and_validate_attachments_from_dsr_builder(
319
328
  self, data: dict, dsr_builder: "DSRReportBuilder"
@@ -342,17 +351,11 @@ class SmartOpenStreamingStorage:
342
351
  else:
343
352
  used_filenames_data.update(filenames)
344
353
 
345
- processed_attachments_list = process_attachments_contextually(
354
+ return self._collect_and_validate_attachments(
346
355
  data,
347
356
  used_filenames_data,
348
357
  used_filenames_attachments,
349
358
  dsr_builder.processed_attachments,
350
- enable_streaming=True, # Always use streaming mode for storage
351
- )
352
-
353
- # Convert to AttachmentProcessingInfo objects using shared utility
354
- return convert_processed_attachments_to_attachment_processing_info(
355
- processed_attachments_list, self._validate_attachment
356
359
  )
357
360
 
358
361
  @retry_cloud_storage_operation(
@@ -374,7 +377,7 @@ class SmartOpenStreamingStorage:
374
377
  """Upload data to cloud storage using smart-open streaming for memory efficiency.
375
378
 
376
379
  This function leverages smart-open's streaming capabilities while maintaining
377
- our DSR-specific business logic for package splitting and attachment processing.
380
+ our DSR-specific business logic for package and attachment processing.
378
381
  All data is streamed directly from source to destination without local storage.
379
382
 
380
383
  Args:
@@ -627,7 +630,12 @@ class SmartOpenStreamingStorage:
627
630
  resp_format: Response format (csv, json)
628
631
  """
629
632
  # Collect and validate all attachments using shared contextual processing
630
- all_attachments = self._collect_and_validate_attachments(data)
633
+ all_attachments = self._collect_and_validate_attachments(
634
+ data=data,
635
+ used_filenames_data=set(),
636
+ used_filenames_attachments=set(),
637
+ processed_attachments={},
638
+ )
631
639
 
632
640
  if not all_attachments:
633
641
  # No attachments, just upload the data
@@ -544,31 +544,9 @@ def _process_attachment_list(
544
544
  return processed_attachments_list
545
545
 
546
546
 
547
- def extract_storage_key_from_attachment(attachment: dict[str, Any]) -> str:
548
- """
549
- Extract storage key from attachment data with fallback logic.
550
-
551
- This function provides a consistent way to extract storage keys from
552
- attachment dictionaries across different components.
553
-
554
- Args:
555
- attachment: The attachment dictionary
556
-
557
- Returns:
558
- The storage key (URL or filename) for the attachment
559
- """
560
- if original_url := attachment.get("original_download_url"):
561
- return original_url
562
-
563
- if download_url := attachment.get("download_url"):
564
- return download_url
565
-
566
- file_name = attachment.get("file_name")
567
- return file_name if file_name is not None else ""
568
-
569
-
570
- def resolve_base_path_from_context(
571
- attachment: dict[str, Any], default_base_path: str = "attachments"
547
+ def resolve_path_from_context(
548
+ attachment: dict[str, Any],
549
+ default_path: str = "attachments",
572
550
  ) -> str:
573
551
  """
574
552
  Resolve the base path for an attachment based on its context.
@@ -578,93 +556,24 @@ def resolve_base_path_from_context(
578
556
 
579
557
  Args:
580
558
  attachment: The attachment dictionary
581
- default_base_path: Default base path if no context is found
559
+ default_path: Default path if no context is found
582
560
 
583
561
  Returns:
584
- The resolved base path for the attachment
562
+ The resolved path for the attachment
585
563
  """
586
564
  if not attachment.get("_context"):
587
- return default_base_path
565
+ return default_path
588
566
 
589
567
  context = attachment["_context"]
590
568
  context_type = context.get("type")
591
569
 
592
- if context_type == "direct":
593
- return f"data/{context['dataset']}/{context['collection']}/attachments"
594
- if context_type == "nested":
595
- return f"data/{context['dataset']}/{context['collection']}/attachments"
570
+ if context_type in ["direct", "nested"]:
571
+ dataset = context.get("dataset", "")
572
+ collection = context.get("collection", "")
573
+ return f"data/{dataset}/{collection}/attachments"
596
574
  if context_type == "top_level":
597
575
  return "attachments"
598
- # Handle old context format
599
576
  if context.get("key") and context.get("item_id"):
600
577
  return f"{context['key']}/{context['item_id']}/attachments"
601
- # Fallback for unknown context types
602
- return "unknown/unknown/attachments"
603
-
604
-
605
- def resolve_directory_from_context(
606
- attachment: dict[str, Any], default_directory: str = "attachments"
607
- ) -> str:
608
- """
609
- Resolve the directory path for an attachment based on its context.
610
-
611
- This function provides consistent directory resolution logic for DSR report builder.
612
-
613
- Args:
614
- attachment: The attachment dictionary
615
- default_directory: Default directory if no context is found
616
-
617
- Returns:
618
- The resolved directory path for the attachment
619
- """
620
- if not attachment.get("_context"):
621
- return default_directory
622
-
623
- context = attachment["_context"]
624
- context_type = context.get("type")
625
-
626
- if context_type == "direct":
627
- return f"data/{context['dataset']}/{context['collection']}"
628
- if context_type == "nested":
629
- return f"data/{context['dataset']}/{context['collection']}"
630
- if context_type == "top_level":
631
- return "attachments"
632
- if context.get("key") and context.get("item_id"):
633
- return f"{context['key']}/{context['item_id']}"
634
-
635
- return default_directory
636
-
637
-
638
- def convert_processed_attachments_to_attachment_processing_info(
639
- processed_attachments_list: list[dict[str, Any]], validate_attachment_func: Callable
640
- ) -> list[Any]:
641
- """
642
- Convert processed attachments list to AttachmentProcessingInfo objects.
643
-
644
- This is a shared utility function to avoid duplication between different
645
- attachment collection methods.
646
-
647
- Args:
648
- processed_attachments_list: List of processed attachment dictionaries
649
- validate_attachment_func: Function to validate individual attachments
650
- Signature: validate_attachment_func(attachment_with_context) -> AttachmentProcessingInfo | None
651
-
652
- Returns:
653
- List of validated AttachmentProcessingInfo objects
654
- """
655
- validated_attachments = []
656
-
657
- for processed_attachment in processed_attachments_list:
658
- attachment_data = processed_attachment["attachment"]
659
-
660
- # Add context information to the attachment data
661
- attachment_with_context = attachment_data.copy()
662
- attachment_with_context["_context"] = processed_attachment["context"]
663
-
664
- # Validate and convert to AttachmentProcessingInfo
665
- if validate_attachment_func is not None:
666
- validated = validate_attachment_func(attachment_with_context)
667
- if validated:
668
- validated_attachments.append(validated)
669
578
 
670
- return validated_attachments
579
+ return default_path
@@ -9,14 +9,13 @@ from fides.api.graph.config import (
9
9
  GraphDataset,
10
10
  ScalarField,
11
11
  )
12
- from fides.api.models.connectionconfig import ConnectionConfig
13
12
 
14
13
  # Import application models
15
- from fides.api.models.manual_task import (
16
- ManualTask,
17
- ManualTaskConditionalDependencyType,
18
- ManualTaskConfigurationType,
14
+ from fides.api.models.conditional_dependency.conditional_dependency_base import (
15
+ ConditionalDependencyType,
19
16
  )
17
+ from fides.api.models.connectionconfig import ConnectionConfig
18
+ from fides.api.models.manual_task import ManualTask, ManualTaskConfigurationType
20
19
  from fides.api.task.manual.manual_task_address import ManualTaskAddress
21
20
 
22
21
  PRIVACY_REQUEST_CONFIG_TYPES = {
@@ -135,7 +134,7 @@ def create_collection_for_connection_key(
135
134
  conditional_field_addresses: set[str] = {
136
135
  dependency.field_address
137
136
  for dependency in manual_task.conditional_dependencies
138
- if dependency.condition_type == ManualTaskConditionalDependencyType.leaf
137
+ if dependency.condition_type == ConditionalDependencyType.leaf
139
138
  and dependency.field_address is not None
140
139
  }
141
140