ethyca-fides 2.64.3b0__py2.py3-none-any.whl → 2.64.5rc3__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 (284) hide show
  1. {ethyca_fides-2.64.3b0.dist-info → ethyca_fides-2.64.5rc3.dist-info}/METADATA +3 -3
  2. {ethyca_fides-2.64.3b0.dist-info → ethyca_fides-2.64.5rc3.dist-info}/RECORD +245 -237
  3. fides/_version.py +3 -3
  4. fides/api/api/v1/api.py +0 -2
  5. fides/api/db/base.py +3 -6
  6. fides/api/db/database.py +2 -27
  7. fides/api/graph/config.py +9 -16
  8. fides/api/models/attachment.py +3 -15
  9. fides/api/models/comment.py +5 -23
  10. fides/api/models/connectionconfig.py +0 -11
  11. fides/api/models/db_cache.py +1 -1
  12. fides/api/models/detection_discovery/core.py +15 -15
  13. fides/api/models/fides_user_respondent_email_verification.py +2 -27
  14. fides/api/models/manual_tasks/__init__.py +14 -0
  15. fides/api/models/manual_tasks/manual_task.py +120 -0
  16. fides/api/models/manual_tasks/manual_task_config.py +136 -0
  17. fides/api/models/manual_tasks/manual_task_log.py +104 -0
  18. fides/api/models/tcf_publisher_restrictions.py +4 -16
  19. fides/api/schemas/manual_tasks/__init__.py +0 -0
  20. fides/api/schemas/manual_tasks/manual_task_config.py +311 -0
  21. fides/api/schemas/manual_tasks/manual_task_schemas.py +79 -0
  22. fides/api/schemas/manual_tasks/manual_task_status.py +151 -0
  23. fides/api/service/connectors/query_configs/bigquery_query_config.py +22 -44
  24. fides/api/service/connectors/query_configs/query_config.py +2 -5
  25. fides/api/util/connection_util.py +2 -25
  26. fides/common/api/v1/urn_registry.py +0 -4
  27. fides/service/manual_tasks/__init__.py +0 -0
  28. fides/service/manual_tasks/manual_task_config_service.py +370 -0
  29. fides/service/manual_tasks/manual_task_service.py +294 -0
  30. fides/service/manual_tasks/utils.py +185 -0
  31. fides/ui-build/static/admin/404.html +1 -1
  32. fides/ui-build/static/admin/_next/static/chunks/{1040-3def3c62138371bb.js → 1040-c1c1372a7f909aef.js} +1 -1
  33. fides/ui-build/static/admin/_next/static/chunks/1100-3fdbdf211c3c2a5b.js +1 -0
  34. fides/ui-build/static/admin/_next/static/chunks/{1817-a3813209d7a6d28d.js → 1817-96182c1558f80b63.js} +1 -1
  35. fides/ui-build/static/admin/_next/static/chunks/2430-b480401d44c55416.js +1 -0
  36. fides/ui-build/static/admin/_next/static/chunks/{2921-81a48418f77bc9a7.js → 2921-f5608275555bd7d9.js} +1 -1
  37. fides/ui-build/static/admin/_next/static/chunks/{3450-3a1f0e80ead8d1b0.js → 3450-272f26c102f3510d.js} +1 -1
  38. fides/ui-build/static/admin/_next/static/chunks/3505-192986c86dc47869.js +1 -0
  39. fides/ui-build/static/admin/_next/static/chunks/3513-a563133845dc990f.js +1 -0
  40. fides/ui-build/static/admin/_next/static/chunks/3670-2abd9b2f17770872.js +1 -0
  41. fides/ui-build/static/admin/_next/static/chunks/{3855-b85ad4e52433d519.js → 3855-beb58821d1ddba89.js} +1 -1
  42. fides/ui-build/static/admin/_next/static/chunks/{3872-09f81435f7905d76.js → 3872-82482e55e69b5a93.js} +1 -1
  43. fides/ui-build/static/admin/_next/static/chunks/{3923-565a852f322fdadc.js → 3923-a54c286a2ba0a47a.js} +1 -1
  44. fides/ui-build/static/admin/_next/static/chunks/3983-17ae9c232bddc413.js +1 -0
  45. fides/ui-build/static/admin/_next/static/chunks/{401-c3f586a23a061526.js → 401-d2ce0a5a9120e056.js} +1 -1
  46. fides/ui-build/static/admin/_next/static/chunks/4060-3486b45081151b69.js +1 -0
  47. fides/ui-build/static/admin/_next/static/chunks/{409-e0d39af1d9ce8ff2.js → 409-86f4f687105917fb.js} +1 -1
  48. fides/ui-build/static/admin/_next/static/chunks/4121-f0aecb2abd384945.js +1 -0
  49. fides/ui-build/static/admin/_next/static/chunks/{4230-d80ae2430aca784a.js → 4230-63abbdfb9e9016b9.js} +1 -1
  50. fides/ui-build/static/admin/_next/static/chunks/{431-c74dab231c8ac968.js → 431-77d59d43e90058ca.js} +1 -1
  51. fides/ui-build/static/admin/_next/static/chunks/4481-d181a9db72984adf.js +1 -0
  52. fides/ui-build/static/admin/_next/static/chunks/{5309-0e44dbd914896514.js → 5309-10f68cf805817cfb.js} +1 -1
  53. fides/ui-build/static/admin/_next/static/chunks/{5574-917c5ff63d222308.js → 5574-b6db9d62362e72d9.js} +1 -1
  54. fides/ui-build/static/admin/_next/static/chunks/6060-cb1ab5be7067bf7b.js +4 -0
  55. fides/ui-build/static/admin/_next/static/chunks/6277-ccdb50f676a1b336.js +1 -0
  56. fides/ui-build/static/admin/_next/static/chunks/6659-b2088f525bf13c17.js +1 -0
  57. fides/ui-build/static/admin/_next/static/chunks/6662-42940a2b00933e79.js +1 -0
  58. fides/ui-build/static/admin/_next/static/chunks/{6853-8d0a099f61c758d1.js → 6853-8a1b8e1c8b249f2f.js} +1 -1
  59. fides/ui-build/static/admin/_next/static/chunks/{6882-13d6f8d95b1e404f.js → 6882-6c94583bffe85ba7.js} +1 -1
  60. fides/ui-build/static/admin/_next/static/chunks/69-943b19d39da339d9.js +1 -0
  61. fides/ui-build/static/admin/_next/static/chunks/{6954-882b87698c5ed4fb.js → 6954-dc3540389daf94da.js} +1 -1
  62. fides/ui-build/static/admin/_next/static/chunks/7553-e7ae268701f3dcfe.js +1 -0
  63. fides/ui-build/static/admin/_next/static/chunks/{79-3f742fe4efd9893f.js → 79-26ccd45dfd6653a7.js} +1 -1
  64. fides/ui-build/static/admin/_next/static/chunks/{796-83a8bbdcdb67f2ba.js → 796-38c0f7e6755ad359.js} +1 -1
  65. fides/ui-build/static/admin/_next/static/chunks/8433-1e065c55c8da73b0.js +1 -0
  66. fides/ui-build/static/admin/_next/static/chunks/{9046-6995482a030e323c.js → 9046-bbce3c73af16daf9.js} +1 -1
  67. fides/ui-build/static/admin/_next/static/chunks/{905-ffdbd0b14167e8bd.js → 905-742074a074be1055.js} +1 -1
  68. fides/ui-build/static/admin/_next/static/chunks/{9226-8a3be36ad1a9c1e7.js → 9226-5e0ce31cfdedd5ee.js} +1 -1
  69. fides/ui-build/static/admin/_next/static/chunks/{9392.9a948112de74781b.js → 9392.25024e070026343d.js} +1 -1
  70. fides/ui-build/static/admin/_next/static/chunks/{9676.cc515c853b8cf578.js → 9676.e60a53f1f5890847.js} +1 -1
  71. fides/ui-build/static/admin/_next/static/chunks/9767-96ed554a043c3c4d.js +1 -0
  72. fides/ui-build/static/admin/_next/static/chunks/{9951-b5b77bfcc8efb493.js → 9951-d3d5d0fe4c4edb86.js} +1 -1
  73. fides/ui-build/static/admin/_next/static/chunks/c78d26b1-88a3e1bacb2a03c2.js +1 -0
  74. fides/ui-build/static/admin/_next/static/chunks/pages/{404-488f8f03fe0ffbc7.js → 404-d41660858638adee.js} +1 -1
  75. fides/ui-build/static/admin/_next/static/chunks/pages/{_app-030b20295bb61f96.js → _app-6b3539f8d82ce9ae.js} +89 -92
  76. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{manual-1e88ac28bc7a41b6.js → manual-7c5e1e845372c99b.js} +1 -1
  77. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{multiple-f2c9451fffaaa529.js → multiple-87e78f52af21c4a9.js} +1 -1
  78. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems-68955d8441e60668.js +1 -0
  79. fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure/{add-vendors-b17d160147365cf3.js → add-vendors-6374a3a7747df964.js} +1 -1
  80. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{configure-8e168d78acdf0cfe.js → configure-0512151e2ed0f4c1.js} +1 -1
  81. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{[id]-5ca2467de7986929.js → [id]-09435f4ab2deafd2.js} +1 -1
  82. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{new-06bb3b0bf097fcdb.js → new-a0039f216fb3eb93.js} +1 -1
  83. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-experience-3c11fecc2797ab68.js → privacy-experience-cd036518b5d4efbe.js} +1 -1
  84. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{[id]-92bc6c7b82a679b4.js → [id]-0e534580abf670be.js} +1 -1
  85. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{new-a3da3243526b7ecb.js → new-bb1790eb87b63109.js} +1 -1
  86. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-notices-b7d82386e7521041.js → privacy-notices-67e9846f877a3f38.js} +1 -1
  87. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{properties-20a2029b7e7fc895.js → properties-69a92b6ddbc2bae2.js} +1 -1
  88. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{reporting-0ce299131db4c3e5.js → reporting-d07d05f4b898a5ed.js} +1 -1
  89. fides/ui-build/static/admin/_next/static/chunks/pages/{consent-9f6a7a231bba17b7.js → consent-23e886d692ab6d1a.js} +1 -1
  90. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]/{[resourceUrn]-11d52f1570759c4d.js → [resourceUrn]-c623d6f1a61c8ea9.js} +1 -1
  91. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/{[projectUrn]-fd705968b357e99a.js → [projectUrn]-6c766c766dc97c5c.js} +1 -1
  92. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{projects-45b585deee0b2371.js → projects-28937a8da3d73145.js} +1 -1
  93. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/resources/{[resourceUrn]-b83afa5565d0c84e.js → [resourceUrn]-57bd5cdf784f059f.js} +1 -1
  94. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{resources-d8db234a44a2ddf4.js → resources-51d99174c8006eb5.js} +1 -1
  95. fides/ui-build/static/admin/_next/static/chunks/pages/{data-catalog-2810fa2b519a076b.js → data-catalog-627fbf19dce88e81.js} +1 -1
  96. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/{[systemId]-e861699a8866c64b.js → [systemId]-ed1629b05519a370.js} +1 -1
  97. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/{[monitorId]-5dd2fbf33e228f9c.js → [monitorId]-ad307bfc5f51fd9d.js} +1 -1
  98. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{action-center-806cae6bc128cd38.js → action-center-07cbd61ede6e18ac.js} +1 -1
  99. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{activity-487285bd5eca2595.js → activity-6a2aaed8d0e66d82.js} +1 -1
  100. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/detection/{[resourceUrn]-393e20924c83373e.js → [resourceUrn]-06edce289876dea1.js} +1 -1
  101. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{detection-8733807dad4bc96e.js → detection-faf326a6200637d0.js} +1 -1
  102. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/discovery/{[resourceUrn]-14bd7500362ff224.js → [resourceUrn]-64acf269256ee74f.js} +1 -1
  103. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{discovery-9e7dfd5a6acc2e8f.js → discovery-8c3e4be6d36da66d.js} +1 -1
  104. fides/ui-build/static/admin/_next/static/chunks/pages/{datamap-c9509d72c538d22b.js → datamap-b576a94b583a7940.js} +1 -1
  105. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/{[...subfieldNames]-4e8a436297a055b2.js → [...subfieldNames]-4912858ffde4621a.js} +1 -1
  106. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/{[collectionName]-6ce02295bb7f5b6d.js → [collectionName]-df21dd7ca0f35718.js} +1 -1
  107. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/{[datasetId]-9eaa907437fde063.js → [datasetId]-5ce28a329e8f667f.js} +1 -1
  108. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/new-5287c76ecf600281.js +1 -0
  109. fides/ui-build/static/admin/_next/static/chunks/pages/{dataset-b328595abf20ea5d.js → dataset-c6fab547396df6ac.js} +1 -1
  110. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{[id]-81ab412e337d2888.js → [id]-d04c9925d324eee1.js} +1 -1
  111. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{new-34dfc172165dbb1c.js → new-656abd09ea5ee39a.js} +1 -1
  112. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection-23fbec0590c8d192.js +1 -0
  113. fides/ui-build/static/admin/_next/static/chunks/pages/{index-de954b741cbca022.js → index-b66687e8194495a2.js} +1 -1
  114. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/{[id]-16dd6eff8f5dcc81.js → [id]-906bc5f05702efb0.js} +1 -1
  115. fides/ui-build/static/admin/_next/static/chunks/pages/integrations-024a1facb9be04d0.js +1 -0
  116. fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{[id]-42edcab11e8b5c3c.js → [id]-b74db8488e2e4b58.js} +1 -1
  117. fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{add-template-333e54ac8c3ad57a.js → add-template-a607018ff097b6c2.js} +1 -1
  118. fides/ui-build/static/admin/_next/static/chunks/pages/{messaging-8e1e6f3782983225.js → messaging-4a1a04c5179d2053.js} +1 -1
  119. fides/ui-build/static/admin/_next/static/chunks/pages/poc/ant-components-1567c9770a5f05aa.js +1 -0
  120. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{AntForm-920338760f5a71b5.js → AntForm-4949fe7f1815462b.js} +1 -1
  121. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikAntFormItem-7462fb387a9de3f8.js → FormikAntFormItem-6085f73850302d55.js} +1 -1
  122. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikControlled-6148fce7a4e2e9ca.js → FormikControlled-a3158e8217c13850.js} +1 -1
  123. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikField-30efd8c937bf19e4.js → FormikField-8576f1ef5c67d87d.js} +1 -1
  124. fides/ui-build/static/admin/_next/static/chunks/pages/poc/{forms-c44de83e0952d1e0.js → forms-341e67462b5e3352.js} +1 -1
  125. fides/ui-build/static/admin/_next/static/chunks/pages/poc/table-migration-6f0e64f0c52bd68f.js +1 -0
  126. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-6971c7773dbf9b51.js +1 -0
  127. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-303bd2182da03088.js +1 -0
  128. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-831572cc7f42615f.js +1 -0
  129. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/{configure-1d981663e1a84166.js → configure-d24230b890b13762.js} +1 -1
  130. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-569ff31eff637034.js +1 -0
  131. fides/ui-build/static/admin/_next/static/chunks/pages/properties/{[id]-b08a69b1c460c7fe.js → [id]-2bedc5013e13ab52.js} +1 -1
  132. fides/ui-build/static/admin/_next/static/chunks/pages/properties/{add-property-a5d1c65ec21df69d.js → add-property-9d68bd70299dd945.js} +1 -1
  133. fides/ui-build/static/admin/_next/static/chunks/pages/{properties-3a75c6ed8308d126.js → properties-c3116b6bfe2e695e.js} +1 -1
  134. fides/ui-build/static/admin/_next/static/chunks/pages/reporting/{datamap-dda59a7105ee609b.js → datamap-6dfa7091b99d8321.js} +1 -1
  135. fides/ui-build/static/admin/_next/static/chunks/pages/settings/about/{alpha-6773158ba6ccf4b0.js → alpha-9751059905bba190.js} +1 -1
  136. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{about-2e046d177d52465c.js → about-ad29d77012ec9dba.js} +1 -1
  137. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent/[configuration_id]/{[purpose_id]-91f2ec72f9654cbd.js → [purpose_id]-32e3190c1ad00b40.js} +1 -1
  138. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-13a17a4ace7293d1.js +1 -0
  139. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{custom-fields-94d97e3eb964c494.js → custom-fields-d2c0aac32f5d2930.js} +1 -1
  140. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domain-records-2c7ecff0a8a74c42.js → domain-records-a10674380f94d014.js} +1 -1
  141. fides/ui-build/static/admin/_next/static/chunks/pages/settings/domains-78449b0e02bced88.js +1 -0
  142. fides/ui-build/static/admin/_next/static/chunks/pages/settings/email-templates-7d299c4cb3199036.js +1 -0
  143. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{locations-8d4383584c72eb5a.js → locations-cc7d629433fa6d44.js} +1 -1
  144. fides/ui-build/static/admin/_next/static/chunks/pages/settings/organization-a9fa55c40fa570a6.js +1 -0
  145. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{regulations-29892065d99ff113.js → regulations-64a813cb2741683b.js} +1 -1
  146. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/test-datasets-547b0cfe1e49e6d2.js +1 -0
  147. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/{[id]-8fa8a2f238e08791.js → [id]-fb3d094e4f4585f6.js} +1 -1
  148. fides/ui-build/static/admin/_next/static/chunks/pages/{systems-acdbdd3dfd21162f.js → systems-c2df5b7b0596a9cb.js} +1 -1
  149. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-261deb6fb3e51cb3.js +1 -0
  150. fides/ui-build/static/admin/_next/static/chunks/pages/user-management/{new-a2524414e968f862.js → new-b124cc24b930c9e1.js} +1 -1
  151. fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/{[id]-87ed17fa1d9f8f72.js → [id]-fd2ff6b13052c54e.js} +1 -1
  152. fides/ui-build/static/admin/_next/static/chunks/pages/{user-management-6b4e0764bb8816b8.js → user-management-fa052b0439920ef6.js} +1 -1
  153. fides/ui-build/static/admin/_next/static/chunks/{webpack-da78c536f3d86d06.js → webpack-e61d457474e00565.js} +1 -1
  154. fides/ui-build/static/admin/_next/static/css/{1994066ec907b7df.css → c693338e3bc8dcc6.css} +1 -1
  155. fides/ui-build/static/admin/_next/static/g740PFm_oIYCWNhoD6-r0/_buildManifest.js +1 -0
  156. fides/ui-build/static/admin/add-systems/manual.html +1 -1
  157. fides/ui-build/static/admin/add-systems/multiple.html +1 -1
  158. fides/ui-build/static/admin/add-systems.html +1 -1
  159. fides/ui-build/static/admin/consent/configure/add-vendors.html +1 -1
  160. fides/ui-build/static/admin/consent/configure.html +1 -1
  161. fides/ui-build/static/admin/consent/privacy-experience/[id].html +1 -1
  162. fides/ui-build/static/admin/consent/privacy-experience/new.html +1 -1
  163. fides/ui-build/static/admin/consent/privacy-experience.html +1 -1
  164. fides/ui-build/static/admin/consent/privacy-notices/[id].html +1 -1
  165. fides/ui-build/static/admin/consent/privacy-notices/new.html +1 -1
  166. fides/ui-build/static/admin/consent/privacy-notices.html +1 -1
  167. fides/ui-build/static/admin/consent/properties.html +1 -1
  168. fides/ui-build/static/admin/consent/reporting.html +1 -1
  169. fides/ui-build/static/admin/consent.html +1 -1
  170. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn].html +1 -1
  171. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn].html +1 -1
  172. fides/ui-build/static/admin/data-catalog/[systemId]/projects.html +1 -1
  173. fides/ui-build/static/admin/data-catalog/[systemId]/resources/[resourceUrn].html +1 -1
  174. fides/ui-build/static/admin/data-catalog/[systemId]/resources.html +1 -1
  175. fides/ui-build/static/admin/data-catalog.html +1 -1
  176. fides/ui-build/static/admin/data-discovery/action-center/[monitorId]/[systemId].html +1 -1
  177. fides/ui-build/static/admin/data-discovery/action-center/[monitorId].html +1 -1
  178. fides/ui-build/static/admin/data-discovery/action-center.html +1 -1
  179. fides/ui-build/static/admin/data-discovery/activity.html +1 -1
  180. fides/ui-build/static/admin/data-discovery/detection/[resourceUrn].html +1 -1
  181. fides/ui-build/static/admin/data-discovery/detection.html +1 -1
  182. fides/ui-build/static/admin/data-discovery/discovery/[resourceUrn].html +1 -1
  183. fides/ui-build/static/admin/data-discovery/discovery.html +1 -1
  184. fides/ui-build/static/admin/datamap.html +1 -1
  185. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName]/[...subfieldNames].html +1 -1
  186. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName].html +1 -1
  187. fides/ui-build/static/admin/dataset/[datasetId].html +1 -1
  188. fides/ui-build/static/admin/dataset/new.html +1 -1
  189. fides/ui-build/static/admin/dataset.html +1 -1
  190. fides/ui-build/static/admin/datastore-connection/[id].html +1 -1
  191. fides/ui-build/static/admin/datastore-connection/new.html +1 -1
  192. fides/ui-build/static/admin/datastore-connection.html +1 -1
  193. fides/ui-build/static/admin/index.html +1 -1
  194. fides/ui-build/static/admin/integrations/[id].html +1 -1
  195. fides/ui-build/static/admin/integrations.html +1 -1
  196. fides/ui-build/static/admin/lib/fides-ext-gpp.js +1 -1
  197. fides/ui-build/static/admin/lib/fides-headless.js +1 -1
  198. fides/ui-build/static/admin/lib/fides-preview.js +1 -1
  199. fides/ui-build/static/admin/lib/fides-tcf.js +2 -2
  200. fides/ui-build/static/admin/lib/fides.js +2 -2
  201. fides/ui-build/static/admin/login/[provider].html +1 -1
  202. fides/ui-build/static/admin/login.html +1 -1
  203. fides/ui-build/static/admin/messaging/[id].html +1 -1
  204. fides/ui-build/static/admin/messaging/add-template.html +1 -1
  205. fides/ui-build/static/admin/messaging.html +1 -1
  206. fides/ui-build/static/admin/poc/ant-components.html +1 -1
  207. fides/ui-build/static/admin/poc/form-experiments/AntForm.html +1 -1
  208. fides/ui-build/static/admin/poc/form-experiments/FormikAntFormItem.html +1 -1
  209. fides/ui-build/static/admin/poc/form-experiments/FormikControlled.html +1 -1
  210. fides/ui-build/static/admin/poc/form-experiments/FormikField.html +1 -1
  211. fides/ui-build/static/admin/poc/form-experiments/FormikSpreadField.html +1 -1
  212. fides/ui-build/static/admin/poc/forms.html +1 -1
  213. fides/ui-build/static/admin/poc/table-migration.html +1 -1
  214. fides/ui-build/static/admin/privacy-requests/[id].html +1 -1
  215. fides/ui-build/static/admin/privacy-requests/configure/messaging.html +1 -1
  216. fides/ui-build/static/admin/privacy-requests/configure/storage.html +1 -1
  217. fides/ui-build/static/admin/privacy-requests/configure.html +1 -1
  218. fides/ui-build/static/admin/privacy-requests.html +1 -1
  219. fides/ui-build/static/admin/properties/[id].html +1 -1
  220. fides/ui-build/static/admin/properties/add-property.html +1 -1
  221. fides/ui-build/static/admin/properties.html +1 -1
  222. fides/ui-build/static/admin/reporting/datamap.html +1 -1
  223. fides/ui-build/static/admin/settings/about/alpha.html +1 -1
  224. fides/ui-build/static/admin/settings/about.html +1 -1
  225. fides/ui-build/static/admin/settings/consent/[configuration_id]/[purpose_id].html +1 -1
  226. fides/ui-build/static/admin/settings/consent.html +1 -1
  227. fides/ui-build/static/admin/settings/custom-fields.html +1 -1
  228. fides/ui-build/static/admin/settings/domain-records.html +1 -1
  229. fides/ui-build/static/admin/settings/domains.html +1 -1
  230. fides/ui-build/static/admin/settings/email-templates.html +1 -1
  231. fides/ui-build/static/admin/settings/locations.html +1 -1
  232. fides/ui-build/static/admin/settings/organization.html +1 -1
  233. fides/ui-build/static/admin/settings/regulations.html +1 -1
  234. fides/ui-build/static/admin/systems/configure/[id]/test-datasets.html +1 -1
  235. fides/ui-build/static/admin/systems/configure/[id].html +1 -1
  236. fides/ui-build/static/admin/systems.html +1 -1
  237. fides/ui-build/static/admin/taxonomy.html +1 -1
  238. fides/ui-build/static/admin/user-management/new.html +1 -1
  239. fides/ui-build/static/admin/user-management/profile/[id].html +1 -1
  240. fides/ui-build/static/admin/user-management.html +1 -1
  241. fides/api/alembic/migrations/versions/41a634d8c669_manual_task_restrict_deletes.py +0 -257
  242. fides/api/alembic/migrations/versions/6a76a1fa4f3f_add_manual_task_instance_table.py +0 -256
  243. fides/api/alembic/migrations/versions/aadfe83c5644_add_manual_task_to_connectiontype_enum.py +0 -46
  244. fides/api/api/v1/endpoints/partitioning_endpoints.py +0 -108
  245. fides/api/models/manual_task.py +0 -965
  246. fides/api/schemas/partitioning/__init__.py +0 -17
  247. fides/api/schemas/partitioning/bigquery_time_based_partitioning.py +0 -31
  248. fides/api/schemas/partitioning/time_based_partitioning.py +0 -1376
  249. fides/ui-build/static/admin/_next/static/chunks/1169-76bbada4f3d16538.js +0 -1
  250. fides/ui-build/static/admin/_next/static/chunks/1807-3beab149351d5ded.js +0 -1
  251. fides/ui-build/static/admin/_next/static/chunks/3615-5e2d062d684b8fa1.js +0 -1
  252. fides/ui-build/static/admin/_next/static/chunks/4121-de4ca969faf2b9f4.js +0 -1
  253. fides/ui-build/static/admin/_next/static/chunks/570-c99f07161bd339cd.js +0 -1
  254. fides/ui-build/static/admin/_next/static/chunks/6084-40d5d94561a6093e.js +0 -1
  255. fides/ui-build/static/admin/_next/static/chunks/6662-6a915300505fd9c0.js +0 -1
  256. fides/ui-build/static/admin/_next/static/chunks/7476-aaf8970dbbbe4864.js +0 -1
  257. fides/ui-build/static/admin/_next/static/chunks/7630-c558dc3a199a633d.js +0 -1
  258. fides/ui-build/static/admin/_next/static/chunks/787-9c751615f5816094.js +0 -1
  259. fides/ui-build/static/admin/_next/static/chunks/827-c6fe34fb336467ae.js +0 -1
  260. fides/ui-build/static/admin/_next/static/chunks/9014-eeae6f581158e645.js +0 -1
  261. fides/ui-build/static/admin/_next/static/chunks/9767-1dca308466dce863.js +0 -1
  262. fides/ui-build/static/admin/_next/static/chunks/9826-303b14ef4fc7ab4a.js +0 -1
  263. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems-a8e0bc7b6674f47e.js +0 -1
  264. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/new-55243db34cf77b7e.js +0 -1
  265. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection-cdb77886d7fd4f44.js +0 -1
  266. fides/ui-build/static/admin/_next/static/chunks/pages/integrations-40a3cd14264796e2.js +0 -1
  267. fides/ui-build/static/admin/_next/static/chunks/pages/poc/ant-components-3f62dd959a039fe9.js +0 -1
  268. fides/ui-build/static/admin/_next/static/chunks/pages/poc/table-migration-7852aa60090c8c9a.js +0 -1
  269. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-11dd6152bf6607cc.js +0 -1
  270. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-c50c2ee7d7d2a585.js +0 -1
  271. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-282de19599d67aaf.js +0 -1
  272. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-3f962ade5df86380.js +0 -1
  273. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-0a87f29768425a37.js +0 -1
  274. fides/ui-build/static/admin/_next/static/chunks/pages/settings/domains-b9e77c75c6b77c88.js +0 -1
  275. fides/ui-build/static/admin/_next/static/chunks/pages/settings/email-templates-bb60c397a03558d8.js +0 -1
  276. fides/ui-build/static/admin/_next/static/chunks/pages/settings/organization-4b835393f5274379.js +0 -1
  277. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/test-datasets-9669fa6b20545530.js +0 -1
  278. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-c9510a1eb612323d.js +0 -1
  279. fides/ui-build/static/admin/_next/static/ezJVaZ_Oi_0J2-wPEOvj1/_buildManifest.js +0 -1
  280. {ethyca_fides-2.64.3b0.dist-info → ethyca_fides-2.64.5rc3.dist-info}/WHEEL +0 -0
  281. {ethyca_fides-2.64.3b0.dist-info → ethyca_fides-2.64.5rc3.dist-info}/entry_points.txt +0 -0
  282. {ethyca_fides-2.64.3b0.dist-info → ethyca_fides-2.64.5rc3.dist-info}/licenses/LICENSE +0 -0
  283. {ethyca_fides-2.64.3b0.dist-info → ethyca_fides-2.64.5rc3.dist-info}/top_level.txt +0 -0
  284. /fides/ui-build/static/admin/_next/static/{ezJVaZ_Oi_0J2-wPEOvj1 → g740PFm_oIYCWNhoD6-r0}/_ssgManifest.js +0 -0
@@ -1,965 +0,0 @@
1
- from datetime import datetime, timezone
2
- from enum import Enum
3
- from typing import TYPE_CHECKING, Annotated, Any, Optional, cast
4
-
5
- from pydantic import ConfigDict, Field
6
- from sqlalchemy import (
7
- Boolean,
8
- Column,
9
- DateTime,
10
- ForeignKey,
11
- Index,
12
- Integer,
13
- String,
14
- UniqueConstraint,
15
- )
16
- from sqlalchemy.dialects.postgresql import JSONB
17
- from sqlalchemy.ext.declarative import declared_attr
18
- from sqlalchemy.orm import Session, relationship
19
- from sqlalchemy.sql import func
20
-
21
- from fides.api.db.base_class import Base, FidesBase
22
- from fides.api.db.util import EnumColumn
23
- from fides.api.schemas.base_class import FidesSchema
24
-
25
- if TYPE_CHECKING:
26
- from fides.api.models.attachment import Attachment
27
- from fides.api.models.fides_user import FidesUser
28
-
29
- # ------------------------------------------------------------
30
- # Enums
31
- # ------------------------------------------------------------
32
-
33
-
34
- class ManualTaskExecutionTiming(str, Enum):
35
- """Enum for when a manual task should be executed in the privacy request DAG."""
36
-
37
- pre_execution = "pre_execution" # Execute before the main DAG
38
- post_execution = "post_execution" # Execute after the main DAG
39
- parallel = "parallel" # Execute in parallel with the main DAG
40
-
41
-
42
- class ManualTaskType(str, Enum):
43
- """Enum for manual task types."""
44
-
45
- privacy_request = "privacy_request"
46
- # Add more task types as needed
47
-
48
-
49
- class ManualTaskParentEntityType(str, Enum):
50
- """Enum for manual task parent entity types."""
51
-
52
- connection_config = (
53
- "connection_config" # used for access and erasure privacy requests
54
- )
55
- # Add more parent entity types as needed
56
-
57
-
58
- class ManualTaskEntityType(str, Enum):
59
- """Enum for manual task entity types."""
60
-
61
- privacy_request = "privacy_request"
62
- # Add more entity types as needed
63
-
64
-
65
- class ManualTaskReferenceType(str, Enum):
66
- """Enum for manual task reference types."""
67
-
68
- privacy_request = "privacy_request"
69
- connection_config = "connection_config"
70
- manual_task_config = "manual_task_config"
71
- assigned_user = "assigned_user" # Reference to the user assigned to the task
72
- # Add more reference types as needed
73
-
74
-
75
- class ManualTaskLogStatus(str, Enum):
76
- """Enum for manual task log status."""
77
-
78
- created = "created"
79
- updated = "updated"
80
- in_progress = "in_progress"
81
- complete = "complete"
82
- error = "error"
83
- retrying = "retrying"
84
- paused = "paused"
85
- awaiting_input = "awaiting_input"
86
-
87
-
88
- class ManualTaskConfigurationType(str, Enum):
89
- """Enum for manual task configuration types."""
90
-
91
- access_privacy_request = "access_privacy_request"
92
- erasure_privacy_request = "erasure_privacy_request"
93
- # Add more configuration types as needed
94
-
95
-
96
- class ManualTaskFieldType(str, Enum):
97
- """Enum for manual task field types."""
98
-
99
- text = "text" # Key-value pairs
100
- checkbox = "checkbox" # Boolean value
101
- attachment = "attachment" # File upload
102
- # Add more field types as needed
103
-
104
-
105
- class StatusType(str, Enum):
106
- """Enum for manual task status."""
107
-
108
- pending = "pending"
109
- in_progress = "in_progress"
110
- completed = "completed"
111
- failed = "failed"
112
-
113
- @classmethod
114
- def get_valid_transitions(cls, current_status: "StatusType") -> list["StatusType"]:
115
- """Get valid transitions from the current status."""
116
- transitions = {
117
- cls.pending: [cls.in_progress, cls.failed, cls.completed],
118
- cls.in_progress: [cls.completed, cls.failed],
119
- cls.completed: [],
120
- cls.failed: [cls.pending, cls.in_progress],
121
- }
122
- return transitions.get(current_status, [])
123
-
124
-
125
- # ------------------------------------------------------------
126
- # Schemas
127
- # ------------------------------------------------------------
128
-
129
-
130
- class ManualTaskFieldMetadata(FidesSchema):
131
- """Base schema for manual task field metadata."""
132
-
133
- label: Annotated[str, Field(description="Display label for the field")]
134
- required: Annotated[
135
- bool, Field(default=False, description="Whether the field is required")
136
- ]
137
- help_text: Annotated[
138
- Optional[str],
139
- Field(default=None, description="Help text to display with the field"),
140
- ]
141
- data_uses: Annotated[
142
- Optional[list[str]],
143
- Field(
144
- default=None,
145
- description="List of data uses associated with this field",
146
- ),
147
- ]
148
-
149
- model_config = ConfigDict(extra="allow")
150
-
151
-
152
- # ------------------------------------------------------------
153
- # Models
154
- # ------------------------------------------------------------
155
-
156
-
157
- class ManualTask(Base):
158
- """Model for storing manual tasks.
159
-
160
- This model can be used for both privacy request tasks and general tasks.
161
- For privacy requests, it replaces the functionality of manual webhooks.
162
- For other use cases, it provides a flexible task management system.
163
-
164
- There can only be one ManualTask per parent entity.
165
- You can create multiple Configs for the same ManualTask.
166
- """
167
-
168
- @declared_attr
169
- def __tablename__(cls) -> str:
170
- """Overriding base class method to set the table name."""
171
- return "manual_task"
172
-
173
- # redefined here because there's a minor, unintended discrepancy between
174
- # this `id` field and that of the `Base` class, which explicitly sets `index=True`.
175
- # TODO: we likely should _not_ be setting `index=True` on the `id`
176
- # attribute of the `Base` class, as `primary_key=True` already specifies a
177
- # primary key constraint, which will implicitly create an index for the field.
178
- id = Column(String(255), primary_key=True, default=FidesBase.generate_uuid)
179
- created_at = Column(
180
- DateTime(timezone=True), server_default=func.now(), nullable=False
181
- )
182
- updated_at = Column(
183
- DateTime(timezone=True),
184
- server_default=func.now(),
185
- onupdate=func.now(),
186
- nullable=False,
187
- )
188
-
189
- # Database columns
190
- task_type = Column(
191
- EnumColumn(ManualTaskType),
192
- nullable=False,
193
- default=ManualTaskType.privacy_request,
194
- )
195
- parent_entity_id = Column(String, nullable=False)
196
- parent_entity_type = Column(
197
- EnumColumn(ManualTaskParentEntityType),
198
- nullable=False,
199
- default=ManualTaskParentEntityType.connection_config,
200
- )
201
-
202
- __table_args__ = (
203
- UniqueConstraint(
204
- "parent_entity_id",
205
- "parent_entity_type",
206
- name="uq_manual_task_parent_entity",
207
- ),
208
- Index("ix_manual_task_parent_entity", "parent_entity_type", "parent_entity_id"),
209
- Index("ix_manual_task_task_type", "task_type"),
210
- )
211
-
212
- # Relationships
213
- references = relationship(
214
- "ManualTaskReference",
215
- back_populates="task",
216
- uselist=True,
217
- cascade="all, delete-orphan",
218
- )
219
- logs = relationship(
220
- "ManualTaskLog",
221
- back_populates="task",
222
- primaryjoin="and_(ManualTask.id == ManualTaskLog.task_id)",
223
- order_by="ManualTaskLog.created_at",
224
- )
225
- configs = relationship(
226
- "ManualTaskConfig",
227
- back_populates="task",
228
- uselist=True,
229
- viewonly=True, # No cascade delete - configs are versioned
230
- )
231
- instances = relationship(
232
- "ManualTaskInstance",
233
- back_populates="task",
234
- uselist=True,
235
- viewonly=True, # No cascade delete - instances contain historical data
236
- )
237
- submissions = relationship(
238
- "ManualTaskSubmission",
239
- back_populates="task",
240
- uselist=True,
241
- viewonly=True, # No cascade delete - submissions are historical data
242
- )
243
-
244
- # Properties
245
- @property
246
- def assigned_users(self) -> list[str]:
247
- """Get all users assigned to this task."""
248
- if not self.references:
249
- return []
250
- return [
251
- ref.reference_id
252
- for ref in self.references
253
- if ref.reference_type == ManualTaskReferenceType.assigned_user
254
- ]
255
-
256
- # CRUD Operations
257
- @classmethod
258
- def create(
259
- cls, db: Session, *, data: dict[str, Any], check_name: bool = True
260
- ) -> "ManualTask":
261
- """Create a new manual task."""
262
- task = super().create(db=db, data=data, check_name=check_name)
263
- ManualTaskLog.create_log(
264
- db=db,
265
- task_id=task.id,
266
- status=ManualTaskLogStatus.created,
267
- message=f"Created manual task for {data['task_type']}",
268
- )
269
- return task
270
-
271
-
272
- class ManualTaskInstance(Base):
273
- """Model for tracking task status per entity instance."""
274
-
275
- @declared_attr
276
- def __tablename__(cls) -> str:
277
- """Overriding base class method to set the table name."""
278
- return "manual_task_instance"
279
-
280
- # redefined here because there's a minor, unintended discrepancy between
281
- # this `id` field and that of the `Base` class, which explicitly sets `index=True`.
282
- # TODO: we likely should _not_ be setting `index=True` on the `id`
283
- # attribute of the `Base` class, as `primary_key=True` already specifies a
284
- # primary key constraint, which will implicitly create an index for the field.
285
- id = Column(String(255), primary_key=True, default=FidesBase.generate_uuid)
286
- created_at = Column(
287
- DateTime(timezone=True), server_default=func.now(), nullable=False
288
- )
289
- updated_at = Column(
290
- DateTime(timezone=True),
291
- server_default=func.now(),
292
- onupdate=func.now(),
293
- nullable=False,
294
- )
295
-
296
- # Database columns
297
- task_id = Column(
298
- String,
299
- ForeignKey(
300
- "manual_task.id",
301
- name="manual_task_instance_task_id_fkey",
302
- ondelete="SET NULL",
303
- ),
304
- nullable=True,
305
- )
306
- config_id = Column(
307
- String,
308
- ForeignKey(
309
- "manual_task_config.id",
310
- name="manual_task_instance_config_id_fkey",
311
- ondelete="RESTRICT",
312
- ),
313
- nullable=False,
314
- )
315
- # entity id is the entity that the instance relates to
316
- # (e.g. a privacy request is an entity that has its own manual task instance)
317
- entity_id = Column(String, nullable=False)
318
- entity_type = Column(EnumColumn(ManualTaskEntityType), nullable=False)
319
- # ignore[assignment] because the mypy and sqlalchemy types mismatch
320
- # upgrading to 2.0 allows mapping which provides better type safety visibility.
321
- status = Column(EnumColumn(StatusType), nullable=False, default=StatusType.pending) # type: ignore[assignment]
322
- completed_at = Column(DateTime, nullable=True) # type: ignore[assignment]
323
- completed_by_id = Column(String, nullable=True) # type: ignore[assignment]
324
- due_date = Column(DateTime, nullable=True)
325
-
326
- __table_args__ = (
327
- Index("ix_manual_task_instance_completed_at", "completed_at"),
328
- Index("ix_manual_task_instance_config_id", "config_id"),
329
- Index("ix_manual_task_instance_entity", "entity_type", "entity_id"),
330
- Index("ix_manual_task_instance_entity_id", "entity_id"),
331
- Index("ix_manual_task_instance_entity_type", "entity_type"),
332
- Index("ix_manual_task_instance_status", "status"),
333
- Index("ix_manual_task_instance_task_id", "task_id"),
334
- )
335
-
336
- # Relationships
337
- task = relationship("ManualTask", back_populates="instances")
338
- config = relationship("ManualTaskConfig", back_populates="instances")
339
- submissions = relationship(
340
- "ManualTaskSubmission",
341
- back_populates="instance",
342
- uselist=True,
343
- )
344
- logs = relationship(
345
- "ManualTaskLog",
346
- back_populates="instance",
347
- primaryjoin="ManualTaskInstance.id == ManualTaskLog.instance_id",
348
- cascade="all, delete-orphan",
349
- order_by="ManualTaskLog.created_at",
350
- uselist=True,
351
- )
352
- attachments = relationship(
353
- "Attachment",
354
- secondary="attachment_reference",
355
- primaryjoin="and_(ManualTaskInstance.id == ManualTaskSubmission.instance_id, "
356
- "ManualTaskSubmission.id == AttachmentReference.reference_id, "
357
- "AttachmentReference.reference_type == 'manual_task_submission')",
358
- secondaryjoin="Attachment.id == AttachmentReference.attachment_id",
359
- order_by="Attachment.created_at",
360
- viewonly=True,
361
- uselist=True,
362
- )
363
-
364
- @property
365
- def required_fields(self) -> list["ManualTaskConfigField"]:
366
- """Get all required fields."""
367
- return [
368
- field
369
- for field in self.config.field_definitions
370
- if field.field_metadata.get("required", False)
371
- ]
372
-
373
- @property
374
- def incomplete_fields(self) -> list["ManualTaskConfigField"]:
375
- """Get all fields that haven't been completed yet.
376
- A field is considered incomplete if:
377
- 1. It's required and has no submission
378
- Returns:
379
- list[ManualTaskConfigField]: List of incomplete fields
380
- """
381
- return [
382
- field
383
- for field in self.required_fields
384
- if not self.get_submission_for_field(field.id)
385
- ]
386
-
387
- @property
388
- def completed_fields(self) -> list["ManualTaskConfigField"]:
389
- """Get all fields that have been completed."""
390
- return [
391
- field
392
- for field in self.config.field_definitions
393
- if field.field_metadata.get("required", False)
394
- and self.get_submission_for_field(field.id)
395
- ]
396
-
397
- def get_submission_for_field(
398
- self, field_id: str
399
- ) -> Optional["ManualTaskSubmission"]:
400
- """Get the submission for a specific field.
401
-
402
- Args:
403
- field_id: The ID of the field to get the submission for
404
-
405
- Returns:
406
- Optional[ManualTaskSubmission]: The submission for the field, or None if no submission exists
407
- """
408
- return next(
409
- (
410
- submission
411
- for submission in self.submissions
412
- if submission.field_id == field_id
413
- ),
414
- None,
415
- )
416
-
417
- def update_status(
418
- self, db: Session, new_status: StatusType, user_id: Optional[str] = None
419
- ) -> None:
420
- """Update the status with completion handling."""
421
-
422
- if new_status == StatusType.completed:
423
- self.completed_at = datetime.now(timezone.utc)
424
- self.completed_by_id = user_id
425
- elif new_status == StatusType.pending:
426
- # Reset completion fields if going back to pending
427
- self.completed_at = None
428
- self.completed_by_id = None
429
-
430
- self.status = new_status
431
- db.add(self)
432
- db.commit()
433
-
434
- def mark_completed(self, db: Session, user_id: str) -> None:
435
- """Mark as completed."""
436
- self.update_status(db, StatusType.completed, user_id)
437
-
438
- def delete(self, db: Session) -> None:
439
- """Delete the instance and all associated submissions with proper attachment cleanup."""
440
- # Delete submissions one by one to ensure proper attachment cleanup
441
- for submission in self.submissions:
442
- submission.delete(db)
443
- # Delete the instance itself
444
- db.delete(self)
445
-
446
-
447
- class ManualTaskReference(Base):
448
- """Join table to associate manual tasks with multiple references.
449
-
450
- A single task may have many references including privacy requests, configurations, and assigned users.
451
- """
452
-
453
- @declared_attr
454
- def __tablename__(cls) -> str:
455
- """Overriding base class method to set the table name."""
456
- return "manual_task_reference"
457
-
458
- # redefined here because there's a minor, unintended discrepancy between
459
- # this `id` field and that of the `Base` class, which explicitly sets `index=True`.
460
- # TODO: we likely should _not_ be setting `index=True` on the `id`
461
- # attribute of the `Base` class, as `primary_key=True` already specifies a
462
- # primary key constraint, which will implicitly create an index for the field.
463
- id = Column(String(255), primary_key=True, default=FidesBase.generate_uuid)
464
- created_at = Column(
465
- DateTime(timezone=True), server_default=func.now(), nullable=False
466
- )
467
- updated_at = Column(
468
- DateTime(timezone=True),
469
- server_default=func.now(),
470
- onupdate=func.now(),
471
- nullable=False,
472
- )
473
-
474
- # Database columns
475
- task_id = Column(
476
- String, ForeignKey("manual_task.id", ondelete="CASCADE"), nullable=False
477
- )
478
- reference_id = Column(String, nullable=False)
479
- reference_type = Column(EnumColumn(ManualTaskReferenceType), nullable=False)
480
-
481
- __table_args__ = (
482
- Index("ix_manual_task_reference_reference", "reference_id", "reference_type"),
483
- Index("ix_manual_task_reference_task_id", "task_id"),
484
- )
485
-
486
- # Relationships
487
- task = relationship("ManualTask", back_populates="references")
488
-
489
-
490
- class ManualTaskConfig(Base):
491
- """Model for storing manual task configurations.
492
- A single configuration may have many fields of different types.
493
- """
494
-
495
- @declared_attr
496
- def __tablename__(cls) -> str:
497
- return "manual_task_config"
498
-
499
- # redefined here because there's a minor, unintended discrepancy between
500
- # this `id` field and that of the `Base` class, which explicitly sets `index=True`.
501
- # TODO: we likely should _not_ be setting `index=True` on the `id`
502
- # attribute of the `Base` class, as `primary_key=True` already specifies a
503
- # primary key constraint, which will implicitly create an index for the field.
504
- id = Column(String(255), primary_key=True, default=FidesBase.generate_uuid)
505
- created_at = Column(
506
- DateTime(timezone=True), server_default=func.now(), nullable=False
507
- )
508
- updated_at = Column(
509
- DateTime(timezone=True),
510
- server_default=func.now(),
511
- onupdate=func.now(),
512
- nullable=False,
513
- )
514
-
515
- task_id = Column(
516
- String,
517
- ForeignKey(
518
- "manual_task.id",
519
- name="manual_task_config_task_id_fkey",
520
- ondelete="SET NULL",
521
- ),
522
- nullable=True,
523
- )
524
- config_type = Column(EnumColumn(ManualTaskConfigurationType), nullable=False)
525
- version = Column(Integer, nullable=False, default=1)
526
- is_current = Column(Boolean, nullable=False, default=True)
527
- execution_timing = Column(
528
- EnumColumn(ManualTaskExecutionTiming),
529
- nullable=False,
530
- default=ManualTaskExecutionTiming.pre_execution,
531
- )
532
-
533
- __table_args__ = (
534
- Index("ix_manual_task_config_config_type", "config_type"),
535
- Index("ix_manual_task_config_task_id", "task_id"),
536
- )
537
-
538
- # Relationships
539
- task = relationship("ManualTask", back_populates="configs")
540
- instances = relationship(
541
- "ManualTaskInstance",
542
- back_populates="config",
543
- uselist=True,
544
- viewonly=True,
545
- )
546
- submissions = relationship(
547
- "ManualTaskSubmission",
548
- back_populates="config",
549
- uselist=True,
550
- viewonly=True,
551
- )
552
- field_definitions = relationship(
553
- "ManualTaskConfigField",
554
- back_populates="config",
555
- cascade="all, delete-orphan",
556
- uselist=True,
557
- )
558
- logs = relationship(
559
- "ManualTaskLog",
560
- back_populates="config",
561
- primaryjoin="ManualTaskConfig.id == ManualTaskLog.config_id",
562
- cascade="all, delete-orphan",
563
- )
564
-
565
- @classmethod
566
- def create(
567
- cls, db: Session, *, data: dict[str, Any], check_name: bool = True
568
- ) -> "ManualTaskConfig":
569
- """Create a new manual task configuration."""
570
- # Validate config_type
571
- try:
572
- ManualTaskConfigurationType(data["config_type"])
573
- except ValueError:
574
- raise ValueError(f"Invalid config type: {data['config_type']}")
575
-
576
- config = super().create(db=db, data=data, check_name=check_name)
577
-
578
- # Log the config creation as a task-level log
579
- ManualTaskLog.create_log(
580
- db=db,
581
- task_id=data["task_id"],
582
- config_id=config.id,
583
- status=ManualTaskLogStatus.created,
584
- message=f"Created manual task configuration for {data['config_type']}",
585
- details={
586
- "config_type": data["config_type"],
587
- },
588
- )
589
- return config
590
-
591
- def get_field(self, field_key: str) -> Optional["ManualTaskConfigField"]:
592
- """Get a field by its key."""
593
- for field in self.field_definitions:
594
- if field.field_key == field_key:
595
- return field
596
- return None
597
-
598
-
599
- class ManualTaskConfigField(Base):
600
- """Model for storing fields associated with each config."""
601
-
602
- @declared_attr
603
- def __tablename__(cls) -> str:
604
- return "manual_task_config_field"
605
-
606
- # redefined here because there's a minor, unintended discrepancy between
607
- # this `id` field and that of the `Base` class, which explicitly sets `index=True`.
608
- # TODO: we likely should _not_ be setting `index=True` on the `id`
609
- # attribute of the `Base` class, as `primary_key=True` already specifies a
610
- # primary key constraint, which will implicitly create an index for the field.
611
- id = Column(String(255), primary_key=True, default=FidesBase.generate_uuid)
612
- created_at = Column(
613
- DateTime(timezone=True), server_default=func.now(), nullable=False
614
- )
615
- updated_at = Column(
616
- DateTime(timezone=True),
617
- server_default=func.now(),
618
- onupdate=func.now(),
619
- nullable=False,
620
- )
621
-
622
- task_id = Column(
623
- String,
624
- ForeignKey(
625
- "manual_task.id",
626
- name="manual_task_config_field_task_id_fkey",
627
- ondelete="SET NULL",
628
- ),
629
- nullable=True,
630
- )
631
- config_id = Column(
632
- String,
633
- ForeignKey(
634
- "manual_task_config.id",
635
- name="manual_task_config_field_config_id_fkey",
636
- ondelete="CASCADE",
637
- ),
638
- nullable=False,
639
- )
640
- field_key = Column(String, nullable=False)
641
- field_type = Column(
642
- EnumColumn(ManualTaskFieldType), nullable=False
643
- ) # Using ManualTaskFieldType
644
- field_metadata: dict[str, Any] = cast(
645
- dict[str, Any], Column(JSONB, nullable=False, default={})
646
- )
647
-
648
- __table_args__ = (
649
- UniqueConstraint("config_id", "field_key", name="unique_field_key_per_config"),
650
- Index("ix_manual_task_config_field_config_id", "config_id"),
651
- Index("ix_manual_task_config_field_field_key", "field_key"),
652
- Index("ix_manual_task_config_field_task_id", "task_id"),
653
- )
654
-
655
- # Relationships
656
- config = relationship("ManualTaskConfig", back_populates="field_definitions")
657
- submissions = relationship(
658
- "ManualTaskSubmission",
659
- back_populates="field",
660
- uselist=True,
661
- )
662
-
663
- @property
664
- def field_metadata_model(self) -> ManualTaskFieldMetadata:
665
- """Get the field metadata as a Pydantic model."""
666
- assert isinstance(
667
- self.field_metadata, dict
668
- ), "field_metadata must be a dictionary"
669
- return ManualTaskFieldMetadata.model_validate(self.field_metadata)
670
-
671
- @classmethod
672
- def create(
673
- cls, db: Session, *, data: dict[str, Any], check_name: bool = True
674
- ) -> "ManualTaskConfigField":
675
- """Create a new manual task config field."""
676
- # Get the config to access its task_id and check if it exists
677
- config = (
678
- db.query(ManualTaskConfig)
679
- .filter(ManualTaskConfig.id == data["config_id"])
680
- .first()
681
- )
682
- if not config:
683
- raise ValueError(f"Config with id {data['config_id']} not found")
684
-
685
- # Create the field and let SQLAlchemy complex type validation handled in service.
686
- field = super().create(db=db, data=data, check_name=check_name)
687
-
688
- # Create a log entry
689
- if config.task_id:
690
- ManualTaskLog.create_log(
691
- db=db,
692
- task_id=config.task_id,
693
- config_id=data["config_id"],
694
- status=ManualTaskLogStatus.created,
695
- message=f"Created manual task config field for {data['field_key']}",
696
- )
697
- return field
698
-
699
-
700
- class ManualTaskSubmission(Base):
701
- """Model for storing user submissions.
702
- Each submission represents data for a single field.
703
- """
704
-
705
- @declared_attr
706
- def __tablename__(cls) -> str:
707
- """Overriding base class method to set the table name."""
708
- return "manual_task_submission"
709
-
710
- # redefined here because there's a minor, unintended discrepancy between
711
- # this `id` field and that of the `Base` class, which explicitly sets `index=True`.
712
- # TODO: we likely should _not_ be setting `index=True` on the `id`
713
- # attribute of the `Base` class, as `primary_key=True` already specifies a
714
- # primary key constraint, which will implicitly create an index for the field.
715
- id = Column(String(255), primary_key=True, default=FidesBase.generate_uuid)
716
- created_at = Column(
717
- DateTime(timezone=True), server_default=func.now(), nullable=False
718
- )
719
- updated_at = Column(
720
- DateTime(timezone=True),
721
- server_default=func.now(),
722
- onupdate=func.now(),
723
- nullable=False,
724
- )
725
-
726
- # Database columns
727
- task_id = Column(
728
- String,
729
- ForeignKey(
730
- "manual_task.id",
731
- name="manual_task_submission_task_id_fkey",
732
- ondelete="SET NULL",
733
- ),
734
- nullable=True,
735
- )
736
- config_id = Column(
737
- String,
738
- ForeignKey(
739
- "manual_task_config.id",
740
- name="manual_task_submission_config_id_fkey",
741
- ondelete="RESTRICT",
742
- ),
743
- nullable=False,
744
- )
745
- field_id = Column(
746
- String,
747
- ForeignKey(
748
- "manual_task_config_field.id",
749
- name="manual_task_submission_field_id_fkey",
750
- ondelete="RESTRICT",
751
- ),
752
- nullable=False,
753
- )
754
- instance_id = Column(
755
- String,
756
- ForeignKey(
757
- "manual_task_instance.id",
758
- name="manual_task_submission_instance_id_fkey",
759
- ondelete="CASCADE",
760
- ),
761
- nullable=False,
762
- )
763
- submitted_by = Column(
764
- String,
765
- ForeignKey(
766
- "fidesuser.id",
767
- name="manual_task_submission_submitted_by_fkey",
768
- ondelete="SET NULL",
769
- ),
770
- nullable=True,
771
- )
772
- submitted_at = Column(DateTime, default=datetime.now(timezone.utc), nullable=False)
773
- data = Column(JSONB, nullable=False)
774
-
775
- __table_args__ = (
776
- Index("ix_manual_task_submission_config_id", "config_id"),
777
- Index("ix_manual_task_submission_field_id", "field_id"),
778
- Index("ix_manual_task_submission_instance_field", "instance_id", "field_id"),
779
- Index("ix_manual_task_submission_instance_id", "instance_id"),
780
- Index("ix_manual_task_submission_submitted_at", "submitted_at"),
781
- Index("ix_manual_task_submission_submitted_by", "submitted_by"),
782
- Index("ix_manual_task_submission_task_id", "task_id"),
783
- )
784
-
785
- # Relationships
786
- task = relationship("ManualTask", back_populates="submissions")
787
- config = relationship("ManualTaskConfig", back_populates="submissions")
788
- field = relationship("ManualTaskConfigField", back_populates="submissions")
789
- instance = relationship(
790
- "ManualTaskInstance",
791
- back_populates="submissions",
792
- )
793
- attachments = relationship(
794
- "Attachment",
795
- secondary="attachment_reference",
796
- primaryjoin="and_(ManualTaskSubmission.id == AttachmentReference.reference_id, "
797
- "AttachmentReference.reference_type == 'manual_task_submission')",
798
- secondaryjoin="Attachment.id == AttachmentReference.attachment_id",
799
- order_by="Attachment.created_at",
800
- uselist=True,
801
- viewonly=True, # Make read-only to avoid overlapping relationship warnings
802
- )
803
-
804
- user = relationship(
805
- "FidesUser",
806
- primaryjoin="FidesUser.id == ManualTaskSubmission.submitted_by",
807
- viewonly=True,
808
- )
809
-
810
- def delete(self, db: Session) -> None:
811
- """Delete the submission and all associated attachments."""
812
- from fides.api.models.attachment import Attachment, AttachmentReferenceType
813
-
814
- # Delete attachments associated with this submission
815
- Attachment.delete_attachments_for_reference_and_type(
816
- db, self.id, AttachmentReferenceType.manual_task_submission
817
- )
818
- # Delete the submission itself
819
- db.delete(self)
820
-
821
- @staticmethod
822
- def delete_submissions_for_instance(db: Session, instance_id: str) -> None:
823
- """
824
- Deletes submissions associated with a given instance_id.
825
- Properly handles attachment cleanup for each submission.
826
-
827
- Args:
828
- db: Database session.
829
- instance_id: The instance id to delete submissions for.
830
-
831
- Example:
832
- - Delete all submissions associated with a manual task instance.
833
- ``ManualTaskSubmission.delete_submissions_for_instance(
834
- db, instance.id
835
- )``
836
- """
837
- # Query submissions explicitly to avoid lazy loading
838
- submissions = (
839
- db.query(ManualTaskSubmission)
840
- .filter(ManualTaskSubmission.instance_id == instance_id)
841
- .all()
842
- )
843
-
844
- for submission in submissions:
845
- submission.delete(db)
846
-
847
-
848
- class ManualTaskLog(Base):
849
- """Model for storing manual task execution logs."""
850
-
851
- @declared_attr
852
- def __tablename__(cls) -> str:
853
- """Overriding base class method to set the table name."""
854
- return "manual_task_log"
855
-
856
- # redefined here because there's a minor, unintended discrepancy between
857
- # this `id` field and that of the `Base` class, which explicitly sets `index=True`.
858
- # TODO: we likely should _not_ be setting `index=True` on the `id`
859
- # attribute of the `Base` class, as `primary_key=True` already specifies a
860
- # primary key constraint, which will implicitly create an index for the field.
861
- id = Column(String(255), primary_key=True, default=FidesBase.generate_uuid)
862
- created_at = Column(
863
- DateTime(timezone=True), server_default=func.now(), nullable=False
864
- )
865
- updated_at = Column(
866
- DateTime(timezone=True),
867
- server_default=func.now(),
868
- onupdate=func.now(),
869
- nullable=False,
870
- )
871
-
872
- task_id = Column(
873
- String, ForeignKey("manual_task.id", ondelete="SET NULL"), nullable=True
874
- )
875
- config_id = Column(
876
- String, ForeignKey("manual_task_config.id", ondelete="CASCADE"), nullable=True
877
- )
878
- instance_id = Column(
879
- String,
880
- ForeignKey("manual_task_instance.id", ondelete="CASCADE"),
881
- nullable=True,
882
- )
883
- status = Column(String, nullable=False)
884
- message = Column(String, nullable=True)
885
- details = Column(JSONB, nullable=True)
886
-
887
- __table_args__ = (
888
- Index("ix_manual_task_log_config_id", "config_id"),
889
- Index("ix_manual_task_log_created_at", "created_at"),
890
- Index("ix_manual_task_log_instance_id", "instance_id"),
891
- Index("ix_manual_task_log_status", "status"),
892
- Index("ix_manual_task_log_task_id", "task_id"),
893
- )
894
-
895
- # Relationships
896
- task = relationship("ManualTask", back_populates="logs", foreign_keys=[task_id])
897
- config = relationship(
898
- "ManualTaskConfig",
899
- back_populates="logs",
900
- foreign_keys=[config_id],
901
- )
902
- instance = relationship("ManualTaskInstance", back_populates="logs")
903
-
904
- @classmethod
905
- def create_log(
906
- cls,
907
- db: Session,
908
- task_id: str,
909
- status: "ManualTaskLogStatus",
910
- message: str,
911
- config_id: Optional[str] = None,
912
- instance_id: Optional[str] = None,
913
- details: Optional[dict[str, Any]] = None,
914
- ) -> "ManualTaskLog":
915
- """Create a new task log entry.
916
-
917
- Args:
918
- db: Database session
919
- task_id: ID of the task
920
- status: Status of the log entry
921
- message: Optional message describing the event
922
- details: Optional additional details about the event
923
- """
924
- data = {
925
- "task_id": task_id,
926
- "config_id": config_id,
927
- "instance_id": instance_id,
928
- "status": status,
929
- "message": message,
930
- "details": details,
931
- }
932
- return cls.create(db=db, data=data)
933
-
934
- @classmethod
935
- def create_error_log(
936
- cls,
937
- db: Session,
938
- task_id: str,
939
- message: str,
940
- config_id: Optional[str] = None,
941
- instance_id: Optional[str] = None,
942
- details: Optional[dict[str, Any]] = None,
943
- ) -> "ManualTaskLog":
944
- """Create a new error log entry.
945
-
946
- Args:
947
- db: Database session
948
- task_id: ID of the task
949
- message: Error message describing what went wrong
950
- config_id: Optional ID of the configuration
951
- instance_id: Optional ID of the instance
952
- details: Optional additional details about the error
953
-
954
- Returns:
955
- The created error log entry
956
- """
957
- return cls.create_log(
958
- db=db,
959
- status=ManualTaskLogStatus.error,
960
- task_id=task_id,
961
- config_id=config_id,
962
- instance_id=instance_id,
963
- message=message,
964
- details=details,
965
- )