ethyca-fides 2.62.1b2__py2.py3-none-any.whl → 2.63.0rc0__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.
Files changed (329) hide show
  1. {ethyca_fides-2.62.1b2.dist-info → ethyca_fides-2.63.0rc0.dist-info}/METADATA +1 -1
  2. {ethyca_fides-2.62.1b2.dist-info → ethyca_fides-2.63.0rc0.dist-info}/RECORD +217 -212
  3. fides/_version.py +3 -3
  4. fides/api/alembic/migrations/versions/440a5b9a3493_add_fides_user_respondent_email_.py +80 -0
  5. fides/api/db/base.py +3 -0
  6. fides/api/models/audit_log.py +0 -3
  7. fides/api/models/fides_user.py +51 -4
  8. fides/api/models/fides_user_permissions.py +25 -7
  9. fides/api/models/fides_user_respondent_email_verification.py +112 -0
  10. fides/api/oauth/roles.py +19 -0
  11. fides/api/service/privacy_request/request_runner_service.py +47 -18
  12. fides/api/tasks/storage.py +4 -3
  13. fides/common/api/scope_registry.py +6 -0
  14. fides/ui-build/static/admin/404.html +1 -1
  15. fides/ui-build/static/admin/_next/static/LY2HTf0jAydL8pMpld53D/_buildManifest.js +1 -0
  16. fides/ui-build/static/admin/_next/static/chunks/1099-667e84655846e78c.js +1 -0
  17. fides/ui-build/static/admin/_next/static/chunks/1100-0b01f500b1eaf60d.js +1 -0
  18. fides/ui-build/static/admin/_next/static/chunks/1817-951f58ddd5d46081.js +1 -0
  19. fides/ui-build/static/admin/_next/static/chunks/1904-361e37a5811ed7fc.js +1 -0
  20. fides/ui-build/static/admin/_next/static/chunks/2310-744354001d01f366.js +1 -0
  21. fides/ui-build/static/admin/_next/static/chunks/2921-49af55ad7c631c93.js +1 -0
  22. fides/ui-build/static/admin/_next/static/chunks/3119-e36ae5071c8f27a5.js +1 -0
  23. fides/ui-build/static/admin/_next/static/chunks/3505-113f9c95d34b7aae.js +1 -0
  24. fides/ui-build/static/admin/_next/static/chunks/3513-5c2d412a84a78971.js +1 -0
  25. fides/ui-build/static/admin/_next/static/chunks/3662-f6a1ddca5ee42076.js +1 -0
  26. fides/ui-build/static/admin/_next/static/chunks/3670-2abd9b2f17770872.js +1 -0
  27. fides/ui-build/static/admin/_next/static/chunks/3872-45cc725e241211f0.js +1 -0
  28. fides/ui-build/static/admin/_next/static/chunks/3923-b4f701ada3ef0ee0.js +1 -0
  29. fides/ui-build/static/admin/_next/static/chunks/3983-17ae9c232bddc413.js +1 -0
  30. fides/ui-build/static/admin/_next/static/chunks/401-7e800aed05537126.js +1 -0
  31. fides/ui-build/static/admin/_next/static/chunks/4060-90a52a9afc655bfc.js +1 -0
  32. fides/ui-build/static/admin/_next/static/chunks/4121-66b0e00d5e7ae817.js +1 -0
  33. fides/ui-build/static/admin/_next/static/chunks/4132-9b1731bfec6ee537.js +1 -0
  34. fides/ui-build/static/admin/_next/static/chunks/4481-7f6710c928bb0cb0.js +1 -0
  35. fides/ui-build/static/admin/_next/static/chunks/5258-2079138c8cc34f6c.js +1 -0
  36. fides/ui-build/static/admin/_next/static/chunks/5404-2694509cf5fa96da.js +1 -0
  37. fides/ui-build/static/admin/_next/static/chunks/5487-2cbd8d2169eb2a65.js +1 -0
  38. fides/ui-build/static/admin/_next/static/chunks/5683-37137111b3e769fb.js +1 -0
  39. fides/ui-build/static/admin/_next/static/chunks/6202-081545c7822d09af.js +1 -0
  40. fides/ui-build/static/admin/_next/static/chunks/6277-459e054b2702c60e.js +1 -0
  41. fides/ui-build/static/admin/_next/static/chunks/641-7e4eef3222cbda70.js +1 -0
  42. fides/ui-build/static/admin/_next/static/chunks/6659-b2088f525bf13c17.js +1 -0
  43. fides/ui-build/static/admin/_next/static/chunks/6853-688df0b88fe65fd5.js +1 -0
  44. fides/ui-build/static/admin/_next/static/chunks/69-00cba94689b9e740.js +1 -0
  45. fides/ui-build/static/admin/_next/static/chunks/6954-4e313b4599b8763d.js +1 -0
  46. fides/ui-build/static/admin/_next/static/chunks/7553-08bc3d9f66695111.js +1 -0
  47. fides/ui-build/static/admin/_next/static/chunks/79-fc548561beed136f.js +1 -0
  48. fides/ui-build/static/admin/_next/static/chunks/796-d6586308ed44334b.js +1 -0
  49. fides/ui-build/static/admin/_next/static/chunks/7980-736f9fd1e749ddd2.js +1 -0
  50. fides/ui-build/static/admin/_next/static/chunks/8032-74d94f7bd5b81c89.js +1 -0
  51. fides/ui-build/static/admin/_next/static/chunks/8433-51870336908fb253.js +1 -0
  52. fides/ui-build/static/admin/_next/static/chunks/8499-1fd392d0be9e8ee4.js +1 -0
  53. fides/ui-build/static/admin/_next/static/chunks/9033-fdd87182c15b91e2.js +1 -0
  54. fides/ui-build/static/admin/_next/static/chunks/9327-6a53461c9764b16f.js +1 -0
  55. fides/ui-build/static/admin/_next/static/chunks/{9392.bfca299d4f39a9e0.js → 9392.81edc11e3a175275.js} +1 -1
  56. fides/ui-build/static/admin/_next/static/chunks/9494-1ffb888b95289891.js +1 -0
  57. fides/ui-build/static/admin/_next/static/chunks/9676.61cf5f6d6a083175.js +1 -0
  58. fides/ui-build/static/admin/_next/static/chunks/9767-afd674014a1d1152.js +1 -0
  59. fides/ui-build/static/admin/_next/static/chunks/pages/404-ec04f826f3dd79ea.js +1 -0
  60. fides/ui-build/static/admin/_next/static/chunks/pages/{_app-94950df9c97cd079.js → _app-33bc23b79bffe07c.js} +12 -12
  61. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/manual-1bec086d567aacff.js +1 -0
  62. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/multiple-f68bf100e4e60e88.js +1 -0
  63. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems-effde5cfe49de55f.js +1 -0
  64. fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure/add-vendors-ec95ed8cb0712828.js +1 -0
  65. fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure-4cc195e15e0c3cc8.js +1 -0
  66. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/[id]-be8972c79fb39705.js +1 -0
  67. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{new-7f38473ce267348a.js → new-a0039f216fb3eb93.js} +1 -1
  68. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience-ccf96207de3b74ea.js +1 -0
  69. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/[id]-b9823cc008372cee.js +1 -0
  70. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/new-373f5772ab41bc93.js +1 -0
  71. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices-b9beeee1bde5ca79.js +1 -0
  72. fides/ui-build/static/admin/_next/static/chunks/pages/consent/properties-6ab3a5baafebd199.js +1 -0
  73. fides/ui-build/static/admin/_next/static/chunks/pages/consent/reporting-8562790ae07f17c9.js +1 -0
  74. fides/ui-build/static/admin/_next/static/chunks/pages/consent-42d4d2d6e0253671.js +1 -0
  75. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]-9d1df6d890671b0c.js +1 -0
  76. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects-7eb08af333baaa8e.js +1 -0
  77. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog-bb57eed84f59a932.js +1 -0
  78. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-47eb34aef3e31ac6.js +1 -0
  79. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]-76cefefc53e84c7f.js +1 -0
  80. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-9d8e84a8b4bf568d.js +1 -0
  81. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/activity-c3eaadd88a2e6caa.js +1 -0
  82. fides/ui-build/static/admin/_next/static/chunks/pages/datamap-db45aa864e9dda8a.js +1 -0
  83. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/[...subfieldNames]-d5cfdebc74654337.js +1 -0
  84. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]-618b89228f83435e.js +1 -0
  85. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]-12fc86f15a4c764e.js +1 -0
  86. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/new-c23d18a9b56c2e3c.js +1 -0
  87. fides/ui-build/static/admin/_next/static/chunks/pages/dataset-e3b2d8e3980ab093.js +1 -0
  88. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/[id]-6e27257eccf65f01.js +1 -0
  89. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/new-bbac1f624424282d.js +1 -0
  90. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection-84eb56f5a07bdf4f.js +1 -0
  91. fides/ui-build/static/admin/_next/static/chunks/pages/index-773182b5e35d0045.js +1 -0
  92. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-eb28c927da5bd653.js +1 -0
  93. fides/ui-build/static/admin/_next/static/chunks/pages/integrations-b582e348423e5bf4.js +1 -0
  94. fides/ui-build/static/admin/_next/static/chunks/pages/messaging/[id]-b51bee8680d66b20.js +1 -0
  95. fides/ui-build/static/admin/_next/static/chunks/pages/messaging/add-template-1de479533f733fbd.js +1 -0
  96. fides/ui-build/static/admin/_next/static/chunks/pages/messaging-7dc295b3ed3d2224.js +1 -0
  97. fides/ui-build/static/admin/_next/static/chunks/pages/poc/ant-components-f64dac3392f5ded7.js +1 -0
  98. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/AntForm-eb020bfac4bee532.js +1 -0
  99. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/FormikAntFormItem-0bd62e28b539e114.js +1 -0
  100. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/FormikControlled-936877004113c2a6.js +1 -0
  101. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/FormikField-6416f01524482af9.js +1 -0
  102. fides/ui-build/static/admin/_next/static/chunks/pages/poc/forms-3f4e1313d1f2969b.js +1 -0
  103. fides/ui-build/static/admin/_next/static/chunks/pages/poc/table-migration-1db7a54437db7db0.js +1 -0
  104. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-64236fd0141414fd.js +1 -0
  105. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-8cab04871908cfeb.js +1 -0
  106. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-150d40428245ee0c.js +1 -0
  107. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure-b6c876dceb16ad1b.js +1 -0
  108. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-20cdb2c8a03deae1.js +1 -0
  109. fides/ui-build/static/admin/_next/static/chunks/pages/properties/[id]-54bcc875592d1fb9.js +1 -0
  110. fides/ui-build/static/admin/_next/static/chunks/pages/properties/add-property-644dc669b508a79a.js +1 -0
  111. fides/ui-build/static/admin/_next/static/chunks/pages/properties-9a88220d03e7e02f.js +1 -0
  112. fides/ui-build/static/admin/_next/static/chunks/pages/reporting/datamap-70dc1081df37ea69.js +1 -0
  113. fides/ui-build/static/admin/_next/static/chunks/pages/settings/about/alpha-3c71b4dbcb6fd6c9.js +1 -0
  114. fides/ui-build/static/admin/_next/static/chunks/pages/settings/about-7cb16e0000dd16c9.js +1 -0
  115. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent/[configuration_id]/[purpose_id]-a18d8f12ee8dcf5d.js +1 -0
  116. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-dc220e116ad5c09e.js +1 -0
  117. fides/ui-build/static/admin/_next/static/chunks/pages/settings/custom-fields-55ddc5f25b86f28e.js +1 -0
  118. fides/ui-build/static/admin/_next/static/chunks/pages/settings/domain-records-5ca7decded228bc8.js +1 -0
  119. fides/ui-build/static/admin/_next/static/chunks/pages/settings/domains-a6fafa1be2834c40.js +1 -0
  120. fides/ui-build/static/admin/_next/static/chunks/pages/settings/email-templates-e633750d2b45ddd6.js +1 -0
  121. fides/ui-build/static/admin/_next/static/chunks/pages/settings/locations-3948686cbd372969.js +1 -0
  122. fides/ui-build/static/admin/_next/static/chunks/pages/settings/organization-04ece499c22d23f4.js +1 -0
  123. fides/ui-build/static/admin/_next/static/chunks/pages/settings/regulations-7752305084280cca.js +1 -0
  124. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/test-datasets-9e5f9066be6f218d.js +1 -0
  125. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]-86de9e6d72098e45.js +1 -0
  126. fides/ui-build/static/admin/_next/static/chunks/pages/systems-cac52e6c3abf6a15.js +1 -0
  127. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-60d5930b6855679b.js +1 -0
  128. fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/[id]-b0f4c34752d32c73.js +1 -0
  129. fides/ui-build/static/admin/_next/static/chunks/pages/user-management-7dee83dd6d9292aa.js +1 -0
  130. fides/ui-build/static/admin/_next/static/chunks/{webpack-3a61b934ba2fb620.js → webpack-8457bad7859c44f0.js} +1 -1
  131. fides/ui-build/static/admin/_next/static/css/1fdf5c593349dbc6.css +1 -0
  132. fides/ui-build/static/admin/_next/static/css/e458b5f1afdbb7fc.css +1 -0
  133. fides/ui-build/static/admin/add-systems/manual.html +1 -1
  134. fides/ui-build/static/admin/add-systems/multiple.html +1 -1
  135. fides/ui-build/static/admin/add-systems.html +1 -1
  136. fides/ui-build/static/admin/consent/configure/add-vendors.html +1 -1
  137. fides/ui-build/static/admin/consent/configure.html +1 -1
  138. fides/ui-build/static/admin/consent/privacy-experience/[id].html +1 -1
  139. fides/ui-build/static/admin/consent/privacy-experience/new.html +1 -1
  140. fides/ui-build/static/admin/consent/privacy-experience.html +1 -1
  141. fides/ui-build/static/admin/consent/privacy-notices/[id].html +1 -1
  142. fides/ui-build/static/admin/consent/privacy-notices/new.html +1 -1
  143. fides/ui-build/static/admin/consent/privacy-notices.html +1 -1
  144. fides/ui-build/static/admin/consent/properties.html +1 -1
  145. fides/ui-build/static/admin/consent/reporting.html +1 -1
  146. fides/ui-build/static/admin/consent.html +1 -1
  147. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn].html +1 -1
  148. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn].html +1 -1
  149. fides/ui-build/static/admin/data-catalog/[systemId]/projects.html +1 -1
  150. fides/ui-build/static/admin/data-catalog/[systemId]/resources/[resourceUrn].html +1 -1
  151. fides/ui-build/static/admin/data-catalog/[systemId]/resources.html +1 -1
  152. fides/ui-build/static/admin/data-catalog.html +1 -1
  153. fides/ui-build/static/admin/data-discovery/action-center/[monitorId]/[systemId].html +1 -1
  154. fides/ui-build/static/admin/data-discovery/action-center/[monitorId].html +1 -1
  155. fides/ui-build/static/admin/data-discovery/action-center.html +1 -1
  156. fides/ui-build/static/admin/data-discovery/activity.html +1 -1
  157. fides/ui-build/static/admin/data-discovery/detection/[resourceUrn].html +1 -1
  158. fides/ui-build/static/admin/data-discovery/detection.html +1 -1
  159. fides/ui-build/static/admin/data-discovery/discovery/[resourceUrn].html +1 -1
  160. fides/ui-build/static/admin/data-discovery/discovery.html +1 -1
  161. fides/ui-build/static/admin/datamap.html +1 -1
  162. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName]/[...subfieldNames].html +1 -1
  163. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName].html +1 -1
  164. fides/ui-build/static/admin/dataset/[datasetId].html +1 -1
  165. fides/ui-build/static/admin/dataset/new.html +1 -1
  166. fides/ui-build/static/admin/dataset.html +1 -1
  167. fides/ui-build/static/admin/datastore-connection/[id].html +1 -1
  168. fides/ui-build/static/admin/datastore-connection/new.html +1 -1
  169. fides/ui-build/static/admin/datastore-connection.html +1 -1
  170. fides/ui-build/static/admin/index.html +1 -1
  171. fides/ui-build/static/admin/integrations/[id].html +1 -1
  172. fides/ui-build/static/admin/integrations.html +1 -1
  173. fides/ui-build/static/admin/login/[provider].html +1 -1
  174. fides/ui-build/static/admin/login.html +1 -1
  175. fides/ui-build/static/admin/messaging/[id].html +1 -1
  176. fides/ui-build/static/admin/messaging/add-template.html +1 -1
  177. fides/ui-build/static/admin/messaging.html +1 -1
  178. fides/ui-build/static/admin/poc/ant-components.html +1 -1
  179. fides/ui-build/static/admin/poc/form-experiments/AntForm.html +1 -1
  180. fides/ui-build/static/admin/poc/form-experiments/FormikAntFormItem.html +1 -1
  181. fides/ui-build/static/admin/poc/form-experiments/FormikControlled.html +1 -1
  182. fides/ui-build/static/admin/poc/form-experiments/FormikField.html +1 -1
  183. fides/ui-build/static/admin/poc/form-experiments/FormikSpreadField.html +1 -1
  184. fides/ui-build/static/admin/poc/forms.html +1 -1
  185. fides/ui-build/static/admin/poc/table-migration.html +1 -1
  186. fides/ui-build/static/admin/privacy-requests/[id].html +1 -1
  187. fides/ui-build/static/admin/privacy-requests/configure/messaging.html +1 -1
  188. fides/ui-build/static/admin/privacy-requests/configure/storage.html +1 -1
  189. fides/ui-build/static/admin/privacy-requests/configure.html +1 -1
  190. fides/ui-build/static/admin/privacy-requests.html +1 -1
  191. fides/ui-build/static/admin/properties/[id].html +1 -1
  192. fides/ui-build/static/admin/properties/add-property.html +1 -1
  193. fides/ui-build/static/admin/properties.html +1 -1
  194. fides/ui-build/static/admin/reporting/datamap.html +1 -1
  195. fides/ui-build/static/admin/settings/about/alpha.html +1 -0
  196. fides/ui-build/static/admin/settings/about.html +1 -1
  197. fides/ui-build/static/admin/settings/consent/[configuration_id]/[purpose_id].html +1 -1
  198. fides/ui-build/static/admin/settings/consent.html +1 -1
  199. fides/ui-build/static/admin/settings/custom-fields.html +1 -1
  200. fides/ui-build/static/admin/settings/domain-records.html +1 -1
  201. fides/ui-build/static/admin/settings/domains.html +1 -1
  202. fides/ui-build/static/admin/settings/email-templates.html +1 -1
  203. fides/ui-build/static/admin/settings/locations.html +1 -1
  204. fides/ui-build/static/admin/settings/organization.html +1 -1
  205. fides/ui-build/static/admin/settings/regulations.html +1 -1
  206. fides/ui-build/static/admin/systems/configure/[id]/test-datasets.html +1 -1
  207. fides/ui-build/static/admin/systems/configure/[id].html +1 -1
  208. fides/ui-build/static/admin/systems.html +1 -1
  209. fides/ui-build/static/admin/taxonomy.html +1 -1
  210. fides/ui-build/static/admin/user-management/new.html +1 -1
  211. fides/ui-build/static/admin/user-management/profile/[id].html +1 -1
  212. fides/ui-build/static/admin/user-management.html +1 -1
  213. fides/ui-build/static/admin/_next/static/chunks/1099-b652e6f9a0cd778b.js +0 -1
  214. fides/ui-build/static/admin/_next/static/chunks/1100-e19e94b0a6486255.js +0 -1
  215. fides/ui-build/static/admin/_next/static/chunks/1327-da0303f70d12fb20.js +0 -1
  216. fides/ui-build/static/admin/_next/static/chunks/1817-d2543e460cec0dcb.js +0 -1
  217. fides/ui-build/static/admin/_next/static/chunks/1904-25e5d4f1b8146fb3.js +0 -1
  218. fides/ui-build/static/admin/_next/static/chunks/2310-6a5fb2f76f7b6491.js +0 -1
  219. fides/ui-build/static/admin/_next/static/chunks/2921-771dc5d9e95dc6b4.js +0 -1
  220. fides/ui-build/static/admin/_next/static/chunks/3119-b5e40d8d24af1e79.js +0 -1
  221. fides/ui-build/static/admin/_next/static/chunks/3426-77fccf2c9a5e10cd.js +0 -1
  222. fides/ui-build/static/admin/_next/static/chunks/3505-313087fc1744a0ca.js +0 -1
  223. fides/ui-build/static/admin/_next/static/chunks/3513-293b1e54699cf3e7.js +0 -1
  224. fides/ui-build/static/admin/_next/static/chunks/3615-5e2d062d684b8fa1.js +0 -1
  225. fides/ui-build/static/admin/_next/static/chunks/3872-99da5bb6140ff810.js +0 -1
  226. fides/ui-build/static/admin/_next/static/chunks/3923-c6dcaeaa3267f254.js +0 -1
  227. fides/ui-build/static/admin/_next/static/chunks/401-a882199f6c94a4dc.js +0 -1
  228. fides/ui-build/static/admin/_next/static/chunks/4060-c657e58514e91e91.js +0 -1
  229. fides/ui-build/static/admin/_next/static/chunks/4121-ec1d8faa3cf5783c.js +0 -1
  230. fides/ui-build/static/admin/_next/static/chunks/4294-5b3aa9d605217915.js +0 -1
  231. fides/ui-build/static/admin/_next/static/chunks/4481-9357e3930d35073b.js +0 -1
  232. fides/ui-build/static/admin/_next/static/chunks/5258-49e73e5998c01254.js +0 -1
  233. fides/ui-build/static/admin/_next/static/chunks/5487-218e4847b8250fbb.js +0 -1
  234. fides/ui-build/static/admin/_next/static/chunks/5683-3d5c4194b1b1493e.js +0 -1
  235. fides/ui-build/static/admin/_next/static/chunks/570-c99f07161bd339cd.js +0 -1
  236. fides/ui-build/static/admin/_next/static/chunks/5973-d776c0029db45971.js +0 -1
  237. fides/ui-build/static/admin/_next/static/chunks/6277-db781b6c1dde3c84.js +0 -1
  238. fides/ui-build/static/admin/_next/static/chunks/6834-dcda0a8ed484775e.js +0 -1
  239. fides/ui-build/static/admin/_next/static/chunks/6853-348fe2ba132b400c.js +0 -1
  240. fides/ui-build/static/admin/_next/static/chunks/69-ef4c11c574b4e6dd.js +0 -1
  241. fides/ui-build/static/admin/_next/static/chunks/6954-04030a21a0c8cf5a.js +0 -1
  242. fides/ui-build/static/admin/_next/static/chunks/7553-0f3e9e7eaf1a8b62.js +0 -1
  243. fides/ui-build/static/admin/_next/static/chunks/79-d877d3bde220da44.js +0 -1
  244. fides/ui-build/static/admin/_next/static/chunks/796-7424eb6391142ccd.js +0 -1
  245. fides/ui-build/static/admin/_next/static/chunks/7980-041df432c4d3a68b.js +0 -1
  246. fides/ui-build/static/admin/_next/static/chunks/8433-755359b501d32eaa.js +0 -1
  247. fides/ui-build/static/admin/_next/static/chunks/8499-06ab15acbfec037c.js +0 -1
  248. fides/ui-build/static/admin/_next/static/chunks/9014-eeae6f581158e645.js +0 -1
  249. fides/ui-build/static/admin/_next/static/chunks/9327-b691be8352e31b58.js +0 -1
  250. fides/ui-build/static/admin/_next/static/chunks/9494-d1fd4fb83c3d4836.js +0 -1
  251. fides/ui-build/static/admin/_next/static/chunks/9676.97fdbec9c2a48c68.js +0 -1
  252. fides/ui-build/static/admin/_next/static/chunks/9767-f8ea7d0127f81294.js +0 -1
  253. fides/ui-build/static/admin/_next/static/chunks/9965-92f4a28823a5e623.js +0 -1
  254. fides/ui-build/static/admin/_next/static/chunks/pages/404-e868487119cd14fc.js +0 -1
  255. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/manual-1292fd216f2839c7.js +0 -1
  256. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/multiple-2ffc37614e9d1fa9.js +0 -1
  257. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems-0234733a90ed5127.js +0 -1
  258. fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure/add-vendors-c8033d6560635046.js +0 -1
  259. fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure-2ba21b95aa3bb15e.js +0 -1
  260. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/[id]-94391554a7607c5b.js +0 -1
  261. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience-fd71fb440dbe60e4.js +0 -1
  262. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/[id]-596dd2a35b455f21.js +0 -1
  263. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/new-fa7f0d2639e12a5a.js +0 -1
  264. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices-5a63fc903408412e.js +0 -1
  265. fides/ui-build/static/admin/_next/static/chunks/pages/consent/properties-5960170d492acb03.js +0 -1
  266. fides/ui-build/static/admin/_next/static/chunks/pages/consent/reporting-80bd51f8217edae4.js +0 -1
  267. fides/ui-build/static/admin/_next/static/chunks/pages/consent-dd2a0e3b536b8b42.js +0 -1
  268. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]-a10a0f3e6592f350.js +0 -1
  269. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects-6971531bb09dff3a.js +0 -1
  270. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog-4dbc71d8be9765f3.js +0 -1
  271. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-67ddc090cf949af4.js +0 -1
  272. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]-07ff657ee49e5742.js +0 -1
  273. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-dbc8c95c22b9f2aa.js +0 -1
  274. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/activity-db3853a09933097a.js +0 -1
  275. fides/ui-build/static/admin/_next/static/chunks/pages/datamap-3aaa99709d83a1f6.js +0 -1
  276. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/[...subfieldNames]-c08363922838022a.js +0 -1
  277. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]-f12df2140e309dfb.js +0 -1
  278. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]-3f564c8d6cfb03d4.js +0 -1
  279. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/new-157b00d23b651d12.js +0 -1
  280. fides/ui-build/static/admin/_next/static/chunks/pages/dataset-9d29dd6cf109891d.js +0 -1
  281. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/[id]-b078218865a8fd28.js +0 -1
  282. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/new-b01f89d250ff52af.js +0 -1
  283. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection-9fc15228581786e6.js +0 -1
  284. fides/ui-build/static/admin/_next/static/chunks/pages/index-2e6ba5382358fcf8.js +0 -1
  285. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-43abc599f0768331.js +0 -1
  286. fides/ui-build/static/admin/_next/static/chunks/pages/integrations-d69c9f1007e76046.js +0 -1
  287. fides/ui-build/static/admin/_next/static/chunks/pages/messaging/[id]-111b07344f1ee9e4.js +0 -1
  288. fides/ui-build/static/admin/_next/static/chunks/pages/messaging/add-template-c41f368fb6b35de4.js +0 -1
  289. fides/ui-build/static/admin/_next/static/chunks/pages/messaging-71166bf207804754.js +0 -1
  290. fides/ui-build/static/admin/_next/static/chunks/pages/poc/ant-components-3dabaf6828acb2cb.js +0 -1
  291. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/AntForm-784081c774042249.js +0 -1
  292. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/FormikAntFormItem-63905f2382f158cd.js +0 -1
  293. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/FormikControlled-43f6eab28eae7b56.js +0 -1
  294. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/FormikField-e4a07abc908fc9b5.js +0 -1
  295. fides/ui-build/static/admin/_next/static/chunks/pages/poc/forms-71a3bfb94280fc49.js +0 -1
  296. fides/ui-build/static/admin/_next/static/chunks/pages/poc/table-migration-fec150afcfeb3fb5.js +0 -1
  297. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-2862630f0e9e484b.js +0 -1
  298. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-35e58b5ed6b12b2b.js +0 -1
  299. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-bb02092af39446da.js +0 -1
  300. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure-42213855a0a8c209.js +0 -1
  301. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-6baa485385ce0678.js +0 -1
  302. fides/ui-build/static/admin/_next/static/chunks/pages/properties/[id]-d547a1da0b74f00f.js +0 -1
  303. fides/ui-build/static/admin/_next/static/chunks/pages/properties/add-property-a7de6f8409a76358.js +0 -1
  304. fides/ui-build/static/admin/_next/static/chunks/pages/properties-4a5e8ec41574c6b5.js +0 -1
  305. fides/ui-build/static/admin/_next/static/chunks/pages/reporting/datamap-707551df97d5eebd.js +0 -1
  306. fides/ui-build/static/admin/_next/static/chunks/pages/settings/about-704fc28e61b17247.js +0 -1
  307. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent/[configuration_id]/[purpose_id]-e4df123bef1ff2b1.js +0 -1
  308. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-2fd6b0ff9b6741fc.js +0 -1
  309. fides/ui-build/static/admin/_next/static/chunks/pages/settings/custom-fields-3a829c53d5d723d2.js +0 -1
  310. fides/ui-build/static/admin/_next/static/chunks/pages/settings/domain-records-92e8246170b492b5.js +0 -1
  311. fides/ui-build/static/admin/_next/static/chunks/pages/settings/domains-f0e9ee8756a65540.js +0 -1
  312. fides/ui-build/static/admin/_next/static/chunks/pages/settings/email-templates-a4771098466af1ed.js +0 -1
  313. fides/ui-build/static/admin/_next/static/chunks/pages/settings/locations-4194ce716b81480d.js +0 -1
  314. fides/ui-build/static/admin/_next/static/chunks/pages/settings/organization-b235f961f9ca39a6.js +0 -1
  315. fides/ui-build/static/admin/_next/static/chunks/pages/settings/regulations-8cff97fe57f42ed3.js +0 -1
  316. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/test-datasets-99cd1a12ae0373b0.js +0 -1
  317. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]-01006a55ac873135.js +0 -1
  318. fides/ui-build/static/admin/_next/static/chunks/pages/systems-45990d85a4c5739b.js +0 -1
  319. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-ec739e169cd5eafe.js +0 -1
  320. fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/[id]-603c2bdbd8dc00ca.js +0 -1
  321. fides/ui-build/static/admin/_next/static/chunks/pages/user-management-592e497369673e1a.js +0 -1
  322. fides/ui-build/static/admin/_next/static/css/1b227ba7eabbfe2f.css +0 -1
  323. fides/ui-build/static/admin/_next/static/css/92c81f666644c594.css +0 -1
  324. fides/ui-build/static/admin/_next/static/ulYEH5vwbFjKDz3nI321R/_buildManifest.js +0 -1
  325. {ethyca_fides-2.62.1b2.dist-info → ethyca_fides-2.63.0rc0.dist-info}/WHEEL +0 -0
  326. {ethyca_fides-2.62.1b2.dist-info → ethyca_fides-2.63.0rc0.dist-info}/entry_points.txt +0 -0
  327. {ethyca_fides-2.62.1b2.dist-info → ethyca_fides-2.63.0rc0.dist-info}/licenses/LICENSE +0 -0
  328. {ethyca_fides-2.62.1b2.dist-info → ethyca_fides-2.63.0rc0.dist-info}/top_level.txt +0 -0
  329. /fides/ui-build/static/admin/_next/static/{ulYEH5vwbFjKDz3nI321R → LY2HTf0jAydL8pMpld53D}/_ssgManifest.js +0 -0
fides/_version.py CHANGED
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2025-06-03T15:45:25-0300",
11
+ "date": "2025-06-04T15:43:31-0400",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "2c58fc8696c47cf695b2beb925ac37c9ff867299",
15
- "version": "2.62.1b2"
14
+ "full-revisionid": "01dc75672a6f67a929e0aa20e2eb9e99ccadb0de",
15
+ "version": "2.63.0rc0"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -0,0 +1,80 @@
1
+ """Add fides_user_respondent_email_verification table
2
+
3
+ Revision ID: 440a5b9a3493
4
+ Revises: 2263583b0e44
5
+ Create Date: 2025-05-29 15:41:59.521940
6
+
7
+ """
8
+
9
+ import sqlalchemy as sa
10
+ from alembic import op
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = "440a5b9a3493"
14
+ down_revision = "2263583b0e44"
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade():
20
+ op.create_table(
21
+ "fides_user_respondent_email_verification",
22
+ sa.Column("id", sa.String(), nullable=False),
23
+ sa.Column("user_id", sa.String(), nullable=False),
24
+ sa.Column("access_token", sa.String(), nullable=False),
25
+ sa.Column(
26
+ "access_token_expires_at", sa.DateTime(timezone=True), nullable=False
27
+ ),
28
+ sa.Column("identity_verified_at", sa.DateTime(timezone=True), nullable=True),
29
+ sa.Column(
30
+ "created_at",
31
+ sa.DateTime(timezone=True),
32
+ nullable=False,
33
+ server_default=sa.text("now()"),
34
+ ),
35
+ sa.Column(
36
+ "updated_at",
37
+ sa.DateTime(timezone=True),
38
+ nullable=False,
39
+ server_default=sa.text("now()"),
40
+ ),
41
+ sa.ForeignKeyConstraint(
42
+ ["user_id"],
43
+ ["fidesuser.id"],
44
+ ondelete="CASCADE",
45
+ ),
46
+ sa.PrimaryKeyConstraint("id"),
47
+ )
48
+ op.create_index(
49
+ "ix_fides_user_respondent_email_verification_id",
50
+ "fides_user_respondent_email_verification",
51
+ ["id"],
52
+ unique=True,
53
+ )
54
+ op.create_index(
55
+ "ix_fides_user_respondent_email_verification_access_token",
56
+ "fides_user_respondent_email_verification",
57
+ ["access_token"],
58
+ unique=True,
59
+ )
60
+ op.create_index(
61
+ "ix_fides_user_respondent_email_verification_user_id",
62
+ "fides_user_respondent_email_verification",
63
+ ["user_id"],
64
+ )
65
+
66
+
67
+ def downgrade():
68
+ op.drop_index(
69
+ "ix_fides_user_respondent_email_verification_user_id",
70
+ table_name="fides_user_respondent_email_verification",
71
+ )
72
+ op.drop_index(
73
+ "ix_fides_user_respondent_email_verification_access_token",
74
+ table_name="fides_user_respondent_email_verification",
75
+ )
76
+ op.drop_index(
77
+ "ix_fides_user_respondent_email_verification_id",
78
+ table_name="fides_user_respondent_email_verification",
79
+ )
80
+ op.drop_table("fides_user_respondent_email_verification")
fides/api/db/base.py CHANGED
@@ -22,6 +22,9 @@ from fides.api.models.fides_cloud import FidesCloud
22
22
  from fides.api.models.fides_user import FidesUser
23
23
  from fides.api.models.fides_user_invite import FidesUserInvite
24
24
  from fides.api.models.fides_user_permissions import FidesUserPermissions
25
+ from fides.api.models.fides_user_respondent_email_verification import (
26
+ FidesUserRespondentEmailVerification,
27
+ )
25
28
  from fides.api.models.identity_salt import IdentitySalt
26
29
  from fides.api.models.location_regulation_selections import LocationRegulationSelections
27
30
  from fides.api.models.manual_webhook import AccessManualWebhook
@@ -11,9 +11,6 @@ class AuditLogAction(str, EnumType):
11
11
  """Enum for audit log actions, reflecting what a user did."""
12
12
 
13
13
  approved = "approved"
14
- attachment_uploaded = "attachment_uploaded"
15
- attachment_deleted = "attachment_deleted"
16
- attachment_retrieved = "attachment_retrieved"
17
14
  denied = "denied"
18
15
  email_sent = "email_sent"
19
16
  finished = "finished"
@@ -23,12 +23,16 @@ from fides.api.db.base_class import Base
23
23
  from fides.api.models.audit_log import AuditLog
24
24
 
25
25
  # Intentionally importing SystemManager here to build the FidesUser.systems relationship
26
- from fides.api.models.system_manager import SystemManager # type: ignore[unused-import]
27
26
  from fides.api.schemas.user import DisabledReason
28
27
  from fides.config import CONFIG
29
28
 
30
29
  if TYPE_CHECKING:
30
+ from fides.api.models.fides_user_permissions import FidesUserPermissions
31
+ from fides.api.models.fides_user_respondent_email_verification import (
32
+ FidesUserRespondentEmailVerification,
33
+ )
31
34
  from fides.api.models.sql_models import System # type: ignore[attr-defined]
35
+ from fides.api.models.system_manager import SystemManager
32
36
 
33
37
 
34
38
  class FidesUser(Base):
@@ -71,6 +75,20 @@ class FidesUser(Base):
71
75
  )
72
76
 
73
77
  systems = relationship("System", secondary="systemmanager", back_populates="data_stewards") # type: ignore
78
+ # permissions relationship is defined via backref in FidesUserPermissions
79
+ email_verifications = relationship(
80
+ "FidesUserRespondentEmailVerification",
81
+ back_populates="user",
82
+ cascade="all,delete",
83
+ lazy="dynamic",
84
+ foreign_keys="[FidesUserRespondentEmailVerification.user_id]",
85
+ )
86
+ permissions = relationship(
87
+ "FidesUserPermissions",
88
+ back_populates="user",
89
+ cascade="all,delete",
90
+ uselist=False,
91
+ )
74
92
 
75
93
  @property
76
94
  def system_ids(self) -> List[str]:
@@ -92,12 +110,11 @@ class FidesUser(Base):
92
110
  ) -> FidesUser:
93
111
  """Create a FidesUser by hashing the password with a generated salt
94
112
  and storing the hashed password and the salt"""
113
+ hashed_password = None
114
+ salt = None
95
115
 
96
116
  if password := data.get("password"):
97
117
  hashed_password, salt = FidesUser.hash_password(password)
98
- else:
99
- hashed_password = None
100
- salt = None
101
118
 
102
119
  user = super().create(
103
120
  db,
@@ -117,6 +134,18 @@ class FidesUser(Base):
117
134
 
118
135
  return user # type: ignore
119
136
 
137
+ @classmethod
138
+ def create_respondent(cls, db: Session, data: dict[str, Any]) -> FidesUser:
139
+ """Create a respondent user. This user will not be able to login with a password and
140
+ requires an email address to be provided.
141
+ """
142
+ if not data.get("email_address"):
143
+ raise ValueError("Email address is required for external respondents")
144
+ if data.get("password"):
145
+ raise ValueError("Password login is not allowed for external respondents")
146
+ data["password_login_enabled"] = False
147
+ return cls.create(db, data)
148
+
120
149
  def credentials_valid(self, password: str, encoding: str = "UTF-8") -> bool:
121
150
  """Verifies that the provided password is correct."""
122
151
  if self.salt is None:
@@ -134,6 +163,9 @@ class FidesUser(Base):
134
163
 
135
164
  No validations are performed on the old/existing password within this function.
136
165
  """
166
+ if self.permissions is not None:
167
+ if self.permissions.is_respondent():
168
+ raise ValueError("Password changes are not allowed for respondents")
137
169
 
138
170
  hashed_password, salt = FidesUser.hash_password(new_password)
139
171
  self.hashed_password = hashed_password # type: ignore
@@ -141,6 +173,17 @@ class FidesUser(Base):
141
173
  self.password_reset_at = datetime.utcnow() # type: ignore
142
174
  self.save(db)
143
175
 
176
+ def update_email_address(self, db: Session, new_email_address: str) -> None:
177
+ """Updates the user's email address to the specified value."""
178
+ if self.permissions is not None:
179
+ if self.permissions.is_respondent():
180
+ raise ValueError(
181
+ "Email address changes are not allowed for respondents"
182
+ )
183
+
184
+ self.email_address = new_email_address # type: ignore
185
+ self.save(db)
186
+
144
187
  def set_as_system_manager(self, db: Session, system: System) -> None:
145
188
  """Add a user as one of the system managers for the given system
146
189
  If applicable, also update the systems on the user's client
@@ -157,6 +200,10 @@ class FidesUser(Base):
157
200
  f"User '{self.username}' is already a system manager of '{system.name}'."
158
201
  )
159
202
 
203
+ if self.permissions is not None:
204
+ if self.permissions.is_respondent():
205
+ raise SystemManagerException("Respondents cannot be system managers.")
206
+
160
207
  self.systems.append(system)
161
208
  self.save(db=db)
162
209
 
@@ -1,11 +1,15 @@
1
- from typing import List
1
+ from typing import List, cast
2
2
 
3
3
  from sqlalchemy import ARRAY, Column, ForeignKey, String
4
- from sqlalchemy.orm import backref, relationship
4
+ from sqlalchemy.orm import Session, relationship
5
5
 
6
6
  from fides.api.db.base_class import Base
7
7
  from fides.api.models.fides_user import FidesUser
8
- from fides.api.oauth.roles import ROLES_TO_SCOPES_MAPPING
8
+ from fides.api.oauth.roles import (
9
+ EXTERNAL_RESPONDENT,
10
+ RESPONDENT,
11
+ ROLES_TO_SCOPES_MAPPING,
12
+ )
9
13
 
10
14
 
11
15
  class FidesUserPermissions(Base):
@@ -13,10 +17,7 @@ class FidesUserPermissions(Base):
13
17
 
14
18
  user_id = Column(String, ForeignKey(FidesUser.id), nullable=False, unique=True)
15
19
  roles = Column(ARRAY(String), nullable=False, server_default="{}", default=dict)
16
- user = relationship(
17
- FidesUser,
18
- backref=backref("permissions", cascade="all,delete", uselist=False),
19
- )
20
+ user = relationship(FidesUser, back_populates="permissions", uselist=False)
20
21
 
21
22
  @property
22
23
  def total_scopes(self) -> List[str]:
@@ -26,3 +27,20 @@ class FidesUserPermissions(Base):
26
27
  all_scopes += ROLES_TO_SCOPES_MAPPING.get(role, [])
27
28
 
28
29
  return sorted(list(set(all_scopes)))
30
+
31
+ def is_respondent(self) -> bool:
32
+ """Check if the user is a respondent."""
33
+ return any(role in self.roles for role in [RESPONDENT, EXTERNAL_RESPONDENT])
34
+
35
+ def update_roles(self, db: Session, new_roles: List[str]) -> None:
36
+ """Update the user's roles if allowed.
37
+ Raises ValueError if role changes are not allowed."""
38
+ if self.is_respondent():
39
+ raise ValueError("Role changes are not allowed for respondents")
40
+
41
+ self.roles = new_roles
42
+ self.save(db)
43
+
44
+ def update(self, db: Session, *, data: dict) -> "FidesUserPermissions":
45
+ """Update the user permissions with the provided data."""
46
+ return cast(FidesUserPermissions, super().update(db, data=data))
@@ -0,0 +1,112 @@
1
+ from __future__ import annotations
2
+
3
+ from datetime import datetime, timedelta, timezone
4
+ from typing import TYPE_CHECKING, Any, Optional
5
+
6
+ from sqlalchemy import Column, DateTime, ForeignKey, String
7
+ from sqlalchemy.ext.declarative import declared_attr
8
+ from sqlalchemy.orm import Session, relationship
9
+
10
+ from fides.api.cryptography.cryptographic_util import generate_secure_random_string
11
+ from fides.api.db.base_class import Base
12
+ from fides.api.util.identity_verification import IdentityVerificationMixin
13
+ from fides.config import get_config
14
+
15
+ CONFIG = get_config()
16
+
17
+
18
+ if TYPE_CHECKING:
19
+ from fides.api.models.fides_user import FidesUser
20
+
21
+ # Access links stay active for 45 days - the same as the DSR expiration. A new link is generated for each email.
22
+ # The emails are created for new DSRs which are assigned to the respondent.
23
+ ACCESS_LINK_TTL_DAYS = 45
24
+
25
+
26
+ class FidesUserRespondentEmailVerification(Base, IdentityVerificationMixin):
27
+ """Model for handling email verification for external respondents.
28
+
29
+ This handles two types of verification:
30
+ 1. Access links - long-lived (45 days) for initial access
31
+ 2. Verification codes - short-lived (1 hour) for actual verification
32
+
33
+ When an email is sent to an external respondent, a new verification is created with a new access token is created.
34
+ When a respondent clicks the link in the email, the access token is verified and a verification code is generated.
35
+ The verification code is sent to the respondent's email address and the respondent is prompted to enter the code.
36
+ Verification is handled by the `IdentityVerificationMixin` class.
37
+ """
38
+
39
+ @declared_attr
40
+ def __tablename__(self) -> str:
41
+ return "fides_user_respondent_email_verification"
42
+
43
+ user_id = Column(
44
+ String,
45
+ ForeignKey("fidesuser.id", ondelete="CASCADE"),
46
+ nullable=False,
47
+ index=True,
48
+ )
49
+
50
+ access_token = Column(
51
+ String, nullable=False, unique=True, index=True
52
+ ) # Token for the access link
53
+ access_token_expires_at = Column(DateTime(timezone=True), nullable=False)
54
+ identity_verified_at = Column(DateTime(timezone=True), nullable=True)
55
+
56
+ user = relationship(
57
+ "FidesUser",
58
+ back_populates="email_verifications",
59
+ foreign_keys=[user_id],
60
+ )
61
+
62
+ @classmethod
63
+ def create(
64
+ cls, db: Session, *, data: dict[str, Any], check_name: bool = False
65
+ ) -> FidesUserRespondentEmailVerification:
66
+ """
67
+ Create a FidesUserEmailVerification record with a new access token.
68
+ The verification code will be generated when the access link is used.
69
+ """
70
+ # Generate a secure token for the access link
71
+ access_token = generate_secure_random_string(32)
72
+ expires_at = datetime.now(timezone.utc) + timedelta(days=ACCESS_LINK_TTL_DAYS)
73
+
74
+ verification = super().create(
75
+ db,
76
+ data={
77
+ "user_id": data["user_id"],
78
+ "access_token": access_token,
79
+ "access_token_expires_at": expires_at,
80
+ },
81
+ )
82
+
83
+ return verification
84
+
85
+ def is_access_token_expired(self) -> bool:
86
+ """Check if the access token has expired."""
87
+ if not self.access_token_expires_at:
88
+ return True
89
+
90
+ current_time_utc = datetime.now(timezone.utc)
91
+ return current_time_utc > self.access_token_expires_at
92
+
93
+ def verify_access_token(self, token: str) -> bool:
94
+ """Verify the access token and generate a verification code if valid."""
95
+ if self.is_access_token_expired():
96
+ return False
97
+
98
+ return self.access_token == token
99
+
100
+ def verify_identity(
101
+ self,
102
+ db: Session,
103
+ provided_code: Optional[str] = None,
104
+ ) -> None:
105
+ """A method to call the internal identity verification method provided by the
106
+ `IdentityVerificationMixin`."""
107
+ if self.is_access_token_expired():
108
+ raise ValueError("Access token has expired.")
109
+
110
+ self._verify_identity(provided_code=provided_code)
111
+ self.identity_verified_at = datetime.now(timezone.utc)
112
+ self.save(db)
fides/api/oauth/roles.py CHANGED
@@ -27,6 +27,8 @@ from fides.common.api.scope_registry import (
27
27
  PRIVACY_NOTICE_READ,
28
28
  PRIVACY_REQUEST_CALLBACK_RESUME,
29
29
  PRIVACY_REQUEST_DELETE,
30
+ PRIVACY_REQUEST_MANUAL_STEPS_RESPOND,
31
+ PRIVACY_REQUEST_MANUAL_STEPS_REVIEW,
30
32
  PRIVACY_REQUEST_NOTIFICATIONS_CREATE_OR_UPDATE,
31
33
  PRIVACY_REQUEST_NOTIFICATIONS_READ,
32
34
  PRIVACY_REQUEST_READ,
@@ -52,6 +54,8 @@ CONTRIBUTOR = "contributor"
52
54
  OWNER = "owner"
53
55
  VIEWER = "viewer"
54
56
  VIEWER_AND_APPROVER = "viewer_and_approver"
57
+ RESPONDENT = "respondent"
58
+ EXTERNAL_RESPONDENT = "external_respondent"
55
59
 
56
60
 
57
61
  class RoleRegistryEnum(Enum):
@@ -62,6 +66,8 @@ class RoleRegistryEnum(Enum):
62
66
  Approver - Limited viewer but can approve Privacy Requests
63
67
  Viewer + Approver = Full View and can approve Privacy Requests
64
68
  Contributor - Can't configure storage and messaging
69
+ Respondent - Internal user who can respond to manual steps
70
+ External Respondent - External user who can only respond to assigned manual steps
65
71
  """
66
72
 
67
73
  owner = OWNER
@@ -69,6 +75,8 @@ class RoleRegistryEnum(Enum):
69
75
  viewer = VIEWER
70
76
  approver = APPROVER
71
77
  contributor = CONTRIBUTOR
78
+ respondent = RESPONDENT
79
+ external_respondent = EXTERNAL_RESPONDENT
72
80
 
73
81
 
74
82
  approver_scopes = [
@@ -79,6 +87,7 @@ approver_scopes = [
79
87
  PRIVACY_REQUEST_VIEW_DATA,
80
88
  PRIVACY_REQUEST_DELETE,
81
89
  USER_READ, # allows approver to view user management table and update their own password
90
+ PRIVACY_REQUEST_MANUAL_STEPS_REVIEW, # allows approvers to see all manual steps
82
91
  ]
83
92
 
84
93
 
@@ -114,6 +123,14 @@ viewer_scopes = [ # Intentionally omitted USER_PERMISSION_READ and PRIVACY_REQU
114
123
  USER_READ,
115
124
  ]
116
125
 
126
+ respondent_scopes = [
127
+ PRIVACY_REQUEST_MANUAL_STEPS_RESPOND, # allows respondents to respond to assigned manual steps
128
+ ]
129
+
130
+ external_respondent_scopes = [
131
+ PRIVACY_REQUEST_MANUAL_STEPS_RESPOND, # allows external respondents to respond to assigned manual steps
132
+ ]
133
+
117
134
  not_contributor_scopes = [
118
135
  CONNECTOR_TEMPLATE_REGISTER,
119
136
  STORAGE_CREATE_OR_UPDATE,
@@ -130,6 +147,8 @@ ROLES_TO_SCOPES_MAPPING: Dict[str, List] = {
130
147
  VIEWER: sorted(viewer_scopes),
131
148
  APPROVER: sorted(approver_scopes),
132
149
  CONTRIBUTOR: sorted(list(set(SCOPE_REGISTRY) - set(not_contributor_scopes))),
150
+ RESPONDENT: sorted(respondent_scopes),
151
+ EXTERNAL_RESPONDENT: sorted(external_respondent_scopes),
133
152
  }
134
153
 
135
154
 
@@ -1,3 +1,4 @@
1
+ import time
1
2
  from datetime import datetime, timedelta
2
3
  from typing import Any, Dict, List, Optional, Set, Tuple
3
4
 
@@ -67,6 +68,7 @@ from fides.api.tasks import DatabaseTask, celery_app
67
68
  from fides.api.tasks.scheduled.scheduler import scheduler
68
69
  from fides.api.util.collection_util import Row
69
70
  from fides.api.util.logger import Pii, _log_exception, _log_warning
71
+ from fides.api.util.logger_context_utils import LoggerContextKeys, log_context
70
72
  from fides.common.api.v1.urn_registry import (
71
73
  PRIVACY_REQUEST_TRANSFER_TO_PARENT,
72
74
  V1_URL_PREFIX,
@@ -200,6 +202,11 @@ def run_webhooks_and_report_status(
200
202
  return True
201
203
 
202
204
 
205
+ @log_context(
206
+ capture_args={
207
+ "privacy_request_id": LoggerContextKeys.privacy_request_id,
208
+ }
209
+ )
203
210
  def upload_access_results( # pylint: disable=R0912
204
211
  session: Session,
205
212
  policy: Policy,
@@ -210,6 +217,7 @@ def upload_access_results( # pylint: disable=R0912
210
217
  fides_connector_datasets: Set[str],
211
218
  ) -> List[str]:
212
219
  """Process the data uploads after the access portion of the privacy request has completed"""
220
+ start_time = time.time()
213
221
  download_urls: List[str] = []
214
222
  if not access_result:
215
223
  logger.info("No results returned for access request")
@@ -251,12 +259,30 @@ def upload_access_results( # pylint: disable=R0912
251
259
  )
252
260
  if download_url:
253
261
  download_urls.append(download_url)
262
+ privacy_request.add_success_execution_log(
263
+ session,
264
+ connection_key=None,
265
+ dataset_name="Access Package Upload",
266
+ collection_name=None,
267
+ message="Access Package Upload successful for privacy request.",
268
+ action_type=ActionType.access,
269
+ )
270
+ logger.bind(
271
+ time_taken=time.time() - start_time,
272
+ ).info("Access Package Upload successful for privacy request.")
254
273
  except common_exceptions.StorageUploadError as exc:
255
- logger.error(
256
- "Error uploading subject access data for rule {} on policy {}: {}",
257
- rule.key,
258
- policy.key,
259
- Pii(str(exc)),
274
+ logger.bind(
275
+ policy_key=policy.key,
276
+ rule_key=rule.key,
277
+ error=Pii(str(exc)),
278
+ ).error("Error uploading subject access data for rule.")
279
+ privacy_request.add_error_execution_log(
280
+ session,
281
+ connection_key=None,
282
+ dataset_name="Access Package Upload",
283
+ collection_name=None,
284
+ message="Access Package Upload failed for privacy request.",
285
+ action_type=ActionType.access,
260
286
  )
261
287
  privacy_request.status = PrivacyRequestStatus.error
262
288
  # Save the results we uploaded to the user for later retrieval
@@ -596,19 +622,22 @@ def run_privacy_request(
596
622
  # If dev mode, log traceback
597
623
  _log_exception(e, CONFIG.dev_mode)
598
624
  return
599
- privacy_request.finished_processing_at = datetime.utcnow()
600
- AuditLog.create(
601
- db=session,
602
- data={
603
- "user_id": "system",
604
- "privacy_request_id": privacy_request.id,
605
- "action": AuditLogAction.finished,
606
- "message": "",
607
- },
608
- )
609
- privacy_request.status = PrivacyRequestStatus.complete
610
- logger.info("Privacy request run completed.")
611
- privacy_request.save(db=session)
625
+
626
+ # Only mark as complete if not in error state
627
+ if privacy_request.status != PrivacyRequestStatus.error:
628
+ privacy_request.finished_processing_at = datetime.utcnow()
629
+ AuditLog.create(
630
+ db=session,
631
+ data={
632
+ "user_id": "system",
633
+ "privacy_request_id": privacy_request.id,
634
+ "action": AuditLogAction.finished,
635
+ "message": "",
636
+ },
637
+ )
638
+ privacy_request.status = PrivacyRequestStatus.complete
639
+ logger.info("Privacy request run completed.")
640
+ privacy_request.save(db=session)
612
641
 
613
642
 
614
643
  def initiate_privacy_request_completion_email(
@@ -11,6 +11,7 @@ from botocore.exceptions import ClientError, ParamValidationError
11
11
  from fideslang.validation import AnyHttpUrlString
12
12
  from loguru import logger
13
13
 
14
+ from fides.api.common_exceptions import StorageUploadError
14
15
  from fides.api.cryptography.cryptographic_util import bytes_to_b64_str
15
16
  from fides.api.schemas.storage.storage import ResponseFormat, StorageSecrets
16
17
  from fides.api.service.privacy_request.dsr_package.dsr_report_builder import (
@@ -160,9 +161,9 @@ def upload_to_s3( # pylint: disable=R0913
160
161
  logger.error(
161
162
  "Encountered error while uploading and generating link for s3 object: {}", e
162
163
  )
163
- raise e
164
+ raise StorageUploadError(f"Error uploading to S3: {e}")
164
165
  except ParamValidationError as e:
165
- raise ValueError(f"The parameters you provided are incorrect: {e}")
166
+ raise StorageUploadError(f"The parameters you provided are incorrect: {e}")
166
167
 
167
168
 
168
169
  def upload_to_gcs(
@@ -205,7 +206,7 @@ def upload_to_gcs(
205
206
  "Encountered error while uploading and generating link for Google Cloud Storage object: {}",
206
207
  e,
207
208
  )
208
- raise e
209
+ raise StorageUploadError(f"Error uploading to Google Cloud Storage: {e}")
209
210
 
210
211
 
211
212
  def upload_to_local(
@@ -37,6 +37,7 @@ EXEC = "exec"
37
37
  FIDES_TAXONOMY = "fides_taxonomy"
38
38
  GENERATE = "generate"
39
39
  INSTANTIATE = "instantiate"
40
+ MANUAL_STEPS = "manual-steps"
40
41
  MASKING = "masking"
41
42
  MESSAGING = "messaging"
42
43
  ORGANIZATION = "organization"
@@ -51,6 +52,7 @@ PRIVACY_REQUEST_NOTIFICATIONS = "privacy-request-notifications"
51
52
  READ = "read"
52
53
  REGISTER = "register"
53
54
  RESET = "reset"
55
+ RESPOND = "respond"
54
56
  RESUME = "resume"
55
57
  REVIEW = "review"
56
58
  RULE = "rule"
@@ -174,6 +176,8 @@ PRIVACY_PREFERENCE_HISTORY_READ = f"{PRIVACY_PREFERENCE_HISTORY}:{READ}"
174
176
  PRIVACY_REQUEST_CALLBACK_RESUME = f"{PRIVACY_REQUEST}:{RESUME}" # User has permission to restart a paused privacy request
175
177
  PRIVACY_REQUEST_CREATE = f"{PRIVACY_REQUEST}:{CREATE}"
176
178
  PRIVACY_REQUEST_DELETE = f"{PRIVACY_REQUEST}:{DELETE}"
179
+ PRIVACY_REQUEST_MANUAL_STEPS_REVIEW = f"{PRIVACY_REQUEST}:{MANUAL_STEPS}:{REVIEW}"
180
+ PRIVACY_REQUEST_MANUAL_STEPS_RESPOND = f"{PRIVACY_REQUEST}:{MANUAL_STEPS}:{RESPOND}"
177
181
  PRIVACY_REQUEST_NOTIFICATIONS_CREATE_OR_UPDATE = (
178
182
  f"{PRIVACY_REQUEST_NOTIFICATIONS}:{CREATE_OR_UPDATE}"
179
183
  )
@@ -312,6 +316,8 @@ SCOPE_DOCS = {
312
316
  PRIVACY_REQUEST_CALLBACK_RESUME: "Restart paused privacy requests",
313
317
  PRIVACY_REQUEST_READ_ACCESS_RESULTS: "Download access data for the privacy request",
314
318
  PRIVACY_REQUEST_DELETE: "Remove privacy requests",
319
+ PRIVACY_REQUEST_MANUAL_STEPS_RESPOND: "Respond to manual steps for the privacy request",
320
+ PRIVACY_REQUEST_MANUAL_STEPS_REVIEW: "Review manual steps for the privacy request",
315
321
  PRIVACY_REQUEST_NOTIFICATIONS_CREATE_OR_UPDATE: "",
316
322
  PRIVACY_REQUEST_NOTIFICATIONS_READ: "",
317
323
  PRIVACY_REQUEST_READ: "View privacy requests",
@@ -1 +1 @@
1
- <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link data-next-font="" rel="preconnect" href="/" crossorigin="anonymous"/><link rel="preload" href="/_next/static/css/1b227ba7eabbfe2f.css" as="style"/><link rel="stylesheet" href="/_next/static/css/1b227ba7eabbfe2f.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-3a61b934ba2fb620.js" defer=""></script><script src="/_next/static/chunks/framework-c92fc3344e6fd165.js" defer=""></script><script src="/_next/static/chunks/main-090643377c8254e6.js" defer=""></script><script src="/_next/static/chunks/pages/_app-94950df9c97cd079.js" defer=""></script><script src="/_next/static/chunks/pages/404-e868487119cd14fc.js" defer=""></script><script src="/_next/static/ulYEH5vwbFjKDz3nI321R/_buildManifest.js" defer=""></script><script src="/_next/static/ulYEH5vwbFjKDz3nI321R/_ssgManifest.js" defer=""></script><style>.data-ant-cssinjs-cache-path{content:"";}</style></head><body><div id="__next"><div style="height:100%;display:flex"></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/404","query":{},"buildId":"ulYEH5vwbFjKDz3nI321R","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link data-next-font="" rel="preconnect" href="/" crossorigin="anonymous"/><link rel="preload" href="/_next/static/css/1fdf5c593349dbc6.css" as="style"/><link rel="stylesheet" href="/_next/static/css/1fdf5c593349dbc6.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-8457bad7859c44f0.js" defer=""></script><script src="/_next/static/chunks/framework-c92fc3344e6fd165.js" defer=""></script><script src="/_next/static/chunks/main-090643377c8254e6.js" defer=""></script><script src="/_next/static/chunks/pages/_app-33bc23b79bffe07c.js" defer=""></script><script src="/_next/static/chunks/pages/404-ec04f826f3dd79ea.js" defer=""></script><script src="/_next/static/LY2HTf0jAydL8pMpld53D/_buildManifest.js" defer=""></script><script src="/_next/static/LY2HTf0jAydL8pMpld53D/_ssgManifest.js" defer=""></script><style>.data-ant-cssinjs-cache-path{content:"";}</style></head><body><div id="__next"><div style="height:100%;display:flex"></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/404","query":{},"buildId":"LY2HTf0jAydL8pMpld53D","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>