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.
- {ethyca_fides-2.64.3b0.dist-info → ethyca_fides-2.64.5rc3.dist-info}/METADATA +3 -3
- {ethyca_fides-2.64.3b0.dist-info → ethyca_fides-2.64.5rc3.dist-info}/RECORD +245 -237
- fides/_version.py +3 -3
- fides/api/api/v1/api.py +0 -2
- fides/api/db/base.py +3 -6
- fides/api/db/database.py +2 -27
- fides/api/graph/config.py +9 -16
- fides/api/models/attachment.py +3 -15
- fides/api/models/comment.py +5 -23
- fides/api/models/connectionconfig.py +0 -11
- fides/api/models/db_cache.py +1 -1
- fides/api/models/detection_discovery/core.py +15 -15
- fides/api/models/fides_user_respondent_email_verification.py +2 -27
- fides/api/models/manual_tasks/__init__.py +14 -0
- fides/api/models/manual_tasks/manual_task.py +120 -0
- fides/api/models/manual_tasks/manual_task_config.py +136 -0
- fides/api/models/manual_tasks/manual_task_log.py +104 -0
- fides/api/models/tcf_publisher_restrictions.py +4 -16
- fides/api/schemas/manual_tasks/__init__.py +0 -0
- fides/api/schemas/manual_tasks/manual_task_config.py +311 -0
- fides/api/schemas/manual_tasks/manual_task_schemas.py +79 -0
- fides/api/schemas/manual_tasks/manual_task_status.py +151 -0
- fides/api/service/connectors/query_configs/bigquery_query_config.py +22 -44
- fides/api/service/connectors/query_configs/query_config.py +2 -5
- fides/api/util/connection_util.py +2 -25
- fides/common/api/v1/urn_registry.py +0 -4
- fides/service/manual_tasks/__init__.py +0 -0
- fides/service/manual_tasks/manual_task_config_service.py +370 -0
- fides/service/manual_tasks/manual_task_service.py +294 -0
- fides/service/manual_tasks/utils.py +185 -0
- fides/ui-build/static/admin/404.html +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{1040-3def3c62138371bb.js → 1040-c1c1372a7f909aef.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/1100-3fdbdf211c3c2a5b.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{1817-a3813209d7a6d28d.js → 1817-96182c1558f80b63.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/2430-b480401d44c55416.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{2921-81a48418f77bc9a7.js → 2921-f5608275555bd7d9.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{3450-3a1f0e80ead8d1b0.js → 3450-272f26c102f3510d.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/3505-192986c86dc47869.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/3513-a563133845dc990f.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/3670-2abd9b2f17770872.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{3855-b85ad4e52433d519.js → 3855-beb58821d1ddba89.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{3872-09f81435f7905d76.js → 3872-82482e55e69b5a93.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{3923-565a852f322fdadc.js → 3923-a54c286a2ba0a47a.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/3983-17ae9c232bddc413.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{401-c3f586a23a061526.js → 401-d2ce0a5a9120e056.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/4060-3486b45081151b69.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{409-e0d39af1d9ce8ff2.js → 409-86f4f687105917fb.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/4121-f0aecb2abd384945.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{4230-d80ae2430aca784a.js → 4230-63abbdfb9e9016b9.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{431-c74dab231c8ac968.js → 431-77d59d43e90058ca.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/4481-d181a9db72984adf.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{5309-0e44dbd914896514.js → 5309-10f68cf805817cfb.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{5574-917c5ff63d222308.js → 5574-b6db9d62362e72d9.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/6060-cb1ab5be7067bf7b.js +4 -0
- fides/ui-build/static/admin/_next/static/chunks/6277-ccdb50f676a1b336.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/6659-b2088f525bf13c17.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/6662-42940a2b00933e79.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{6853-8d0a099f61c758d1.js → 6853-8a1b8e1c8b249f2f.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{6882-13d6f8d95b1e404f.js → 6882-6c94583bffe85ba7.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/69-943b19d39da339d9.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{6954-882b87698c5ed4fb.js → 6954-dc3540389daf94da.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/7553-e7ae268701f3dcfe.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{79-3f742fe4efd9893f.js → 79-26ccd45dfd6653a7.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{796-83a8bbdcdb67f2ba.js → 796-38c0f7e6755ad359.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/8433-1e065c55c8da73b0.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{9046-6995482a030e323c.js → 9046-bbce3c73af16daf9.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{905-ffdbd0b14167e8bd.js → 905-742074a074be1055.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{9226-8a3be36ad1a9c1e7.js → 9226-5e0ce31cfdedd5ee.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{9392.9a948112de74781b.js → 9392.25024e070026343d.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{9676.cc515c853b8cf578.js → 9676.e60a53f1f5890847.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/9767-96ed554a043c3c4d.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{9951-b5b77bfcc8efb493.js → 9951-d3d5d0fe4c4edb86.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/c78d26b1-88a3e1bacb2a03c2.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/{404-488f8f03fe0ffbc7.js → 404-d41660858638adee.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{_app-030b20295bb61f96.js → _app-6b3539f8d82ce9ae.js} +89 -92
- fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{manual-1e88ac28bc7a41b6.js → manual-7c5e1e845372c99b.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{multiple-f2c9451fffaaa529.js → multiple-87e78f52af21c4a9.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/add-systems-68955d8441e60668.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure/{add-vendors-b17d160147365cf3.js → add-vendors-6374a3a7747df964.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/{configure-8e168d78acdf0cfe.js → configure-0512151e2ed0f4c1.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{[id]-5ca2467de7986929.js → [id]-09435f4ab2deafd2.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{new-06bb3b0bf097fcdb.js → new-a0039f216fb3eb93.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-experience-3c11fecc2797ab68.js → privacy-experience-cd036518b5d4efbe.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{[id]-92bc6c7b82a679b4.js → [id]-0e534580abf670be.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{new-a3da3243526b7ecb.js → new-bb1790eb87b63109.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-notices-b7d82386e7521041.js → privacy-notices-67e9846f877a3f38.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/{properties-20a2029b7e7fc895.js → properties-69a92b6ddbc2bae2.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/{reporting-0ce299131db4c3e5.js → reporting-d07d05f4b898a5ed.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{consent-9f6a7a231bba17b7.js → consent-23e886d692ab6d1a.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]/{[resourceUrn]-11d52f1570759c4d.js → [resourceUrn]-c623d6f1a61c8ea9.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/{[projectUrn]-fd705968b357e99a.js → [projectUrn]-6c766c766dc97c5c.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{projects-45b585deee0b2371.js → projects-28937a8da3d73145.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/resources/{[resourceUrn]-b83afa5565d0c84e.js → [resourceUrn]-57bd5cdf784f059f.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{resources-d8db234a44a2ddf4.js → resources-51d99174c8006eb5.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{data-catalog-2810fa2b519a076b.js → data-catalog-627fbf19dce88e81.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/{[systemId]-e861699a8866c64b.js → [systemId]-ed1629b05519a370.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/{[monitorId]-5dd2fbf33e228f9c.js → [monitorId]-ad307bfc5f51fd9d.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{action-center-806cae6bc128cd38.js → action-center-07cbd61ede6e18ac.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{activity-487285bd5eca2595.js → activity-6a2aaed8d0e66d82.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/detection/{[resourceUrn]-393e20924c83373e.js → [resourceUrn]-06edce289876dea1.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{detection-8733807dad4bc96e.js → detection-faf326a6200637d0.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/discovery/{[resourceUrn]-14bd7500362ff224.js → [resourceUrn]-64acf269256ee74f.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{discovery-9e7dfd5a6acc2e8f.js → discovery-8c3e4be6d36da66d.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{datamap-c9509d72c538d22b.js → datamap-b576a94b583a7940.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/{[...subfieldNames]-4e8a436297a055b2.js → [...subfieldNames]-4912858ffde4621a.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/{[collectionName]-6ce02295bb7f5b6d.js → [collectionName]-df21dd7ca0f35718.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/{[datasetId]-9eaa907437fde063.js → [datasetId]-5ce28a329e8f667f.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/new-5287c76ecf600281.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/{dataset-b328595abf20ea5d.js → dataset-c6fab547396df6ac.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{[id]-81ab412e337d2888.js → [id]-d04c9925d324eee1.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{new-34dfc172165dbb1c.js → new-656abd09ea5ee39a.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection-23fbec0590c8d192.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/{index-de954b741cbca022.js → index-b66687e8194495a2.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/integrations/{[id]-16dd6eff8f5dcc81.js → [id]-906bc5f05702efb0.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/integrations-024a1facb9be04d0.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{[id]-42edcab11e8b5c3c.js → [id]-b74db8488e2e4b58.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{add-template-333e54ac8c3ad57a.js → add-template-a607018ff097b6c2.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{messaging-8e1e6f3782983225.js → messaging-4a1a04c5179d2053.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/ant-components-1567c9770a5f05aa.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{AntForm-920338760f5a71b5.js → AntForm-4949fe7f1815462b.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikAntFormItem-7462fb387a9de3f8.js → FormikAntFormItem-6085f73850302d55.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikControlled-6148fce7a4e2e9ca.js → FormikControlled-a3158e8217c13850.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikField-30efd8c937bf19e4.js → FormikField-8576f1ef5c67d87d.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/{forms-c44de83e0952d1e0.js → forms-341e67462b5e3352.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/table-migration-6f0e64f0c52bd68f.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-6971c7773dbf9b51.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-303bd2182da03088.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-831572cc7f42615f.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/{configure-1d981663e1a84166.js → configure-d24230b890b13762.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-569ff31eff637034.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/properties/{[id]-b08a69b1c460c7fe.js → [id]-2bedc5013e13ab52.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/properties/{add-property-a5d1c65ec21df69d.js → add-property-9d68bd70299dd945.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{properties-3a75c6ed8308d126.js → properties-c3116b6bfe2e695e.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/reporting/{datamap-dda59a7105ee609b.js → datamap-6dfa7091b99d8321.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/about/{alpha-6773158ba6ccf4b0.js → alpha-9751059905bba190.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/{about-2e046d177d52465c.js → about-ad29d77012ec9dba.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent/[configuration_id]/{[purpose_id]-91f2ec72f9654cbd.js → [purpose_id]-32e3190c1ad00b40.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-13a17a4ace7293d1.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/{custom-fields-94d97e3eb964c494.js → custom-fields-d2c0aac32f5d2930.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domain-records-2c7ecff0a8a74c42.js → domain-records-a10674380f94d014.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/domains-78449b0e02bced88.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/email-templates-7d299c4cb3199036.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/{locations-8d4383584c72eb5a.js → locations-cc7d629433fa6d44.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/organization-a9fa55c40fa570a6.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/{regulations-29892065d99ff113.js → regulations-64a813cb2741683b.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/test-datasets-547b0cfe1e49e6d2.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/{[id]-8fa8a2f238e08791.js → [id]-fb3d094e4f4585f6.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{systems-acdbdd3dfd21162f.js → systems-c2df5b7b0596a9cb.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-261deb6fb3e51cb3.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/user-management/{new-a2524414e968f862.js → new-b124cc24b930c9e1.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/{[id]-87ed17fa1d9f8f72.js → [id]-fd2ff6b13052c54e.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{user-management-6b4e0764bb8816b8.js → user-management-fa052b0439920ef6.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{webpack-da78c536f3d86d06.js → webpack-e61d457474e00565.js} +1 -1
- fides/ui-build/static/admin/_next/static/css/{1994066ec907b7df.css → c693338e3bc8dcc6.css} +1 -1
- fides/ui-build/static/admin/_next/static/g740PFm_oIYCWNhoD6-r0/_buildManifest.js +1 -0
- fides/ui-build/static/admin/add-systems/manual.html +1 -1
- fides/ui-build/static/admin/add-systems/multiple.html +1 -1
- fides/ui-build/static/admin/add-systems.html +1 -1
- fides/ui-build/static/admin/consent/configure/add-vendors.html +1 -1
- fides/ui-build/static/admin/consent/configure.html +1 -1
- fides/ui-build/static/admin/consent/privacy-experience/[id].html +1 -1
- fides/ui-build/static/admin/consent/privacy-experience/new.html +1 -1
- fides/ui-build/static/admin/consent/privacy-experience.html +1 -1
- fides/ui-build/static/admin/consent/privacy-notices/[id].html +1 -1
- fides/ui-build/static/admin/consent/privacy-notices/new.html +1 -1
- fides/ui-build/static/admin/consent/privacy-notices.html +1 -1
- fides/ui-build/static/admin/consent/properties.html +1 -1
- fides/ui-build/static/admin/consent/reporting.html +1 -1
- fides/ui-build/static/admin/consent.html +1 -1
- fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn].html +1 -1
- fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn].html +1 -1
- fides/ui-build/static/admin/data-catalog/[systemId]/projects.html +1 -1
- fides/ui-build/static/admin/data-catalog/[systemId]/resources/[resourceUrn].html +1 -1
- fides/ui-build/static/admin/data-catalog/[systemId]/resources.html +1 -1
- fides/ui-build/static/admin/data-catalog.html +1 -1
- fides/ui-build/static/admin/data-discovery/action-center/[monitorId]/[systemId].html +1 -1
- fides/ui-build/static/admin/data-discovery/action-center/[monitorId].html +1 -1
- fides/ui-build/static/admin/data-discovery/action-center.html +1 -1
- fides/ui-build/static/admin/data-discovery/activity.html +1 -1
- fides/ui-build/static/admin/data-discovery/detection/[resourceUrn].html +1 -1
- fides/ui-build/static/admin/data-discovery/detection.html +1 -1
- fides/ui-build/static/admin/data-discovery/discovery/[resourceUrn].html +1 -1
- fides/ui-build/static/admin/data-discovery/discovery.html +1 -1
- fides/ui-build/static/admin/datamap.html +1 -1
- fides/ui-build/static/admin/dataset/[datasetId]/[collectionName]/[...subfieldNames].html +1 -1
- fides/ui-build/static/admin/dataset/[datasetId]/[collectionName].html +1 -1
- fides/ui-build/static/admin/dataset/[datasetId].html +1 -1
- fides/ui-build/static/admin/dataset/new.html +1 -1
- fides/ui-build/static/admin/dataset.html +1 -1
- fides/ui-build/static/admin/datastore-connection/[id].html +1 -1
- fides/ui-build/static/admin/datastore-connection/new.html +1 -1
- fides/ui-build/static/admin/datastore-connection.html +1 -1
- fides/ui-build/static/admin/index.html +1 -1
- fides/ui-build/static/admin/integrations/[id].html +1 -1
- fides/ui-build/static/admin/integrations.html +1 -1
- fides/ui-build/static/admin/lib/fides-ext-gpp.js +1 -1
- fides/ui-build/static/admin/lib/fides-headless.js +1 -1
- fides/ui-build/static/admin/lib/fides-preview.js +1 -1
- fides/ui-build/static/admin/lib/fides-tcf.js +2 -2
- fides/ui-build/static/admin/lib/fides.js +2 -2
- fides/ui-build/static/admin/login/[provider].html +1 -1
- fides/ui-build/static/admin/login.html +1 -1
- fides/ui-build/static/admin/messaging/[id].html +1 -1
- fides/ui-build/static/admin/messaging/add-template.html +1 -1
- fides/ui-build/static/admin/messaging.html +1 -1
- fides/ui-build/static/admin/poc/ant-components.html +1 -1
- fides/ui-build/static/admin/poc/form-experiments/AntForm.html +1 -1
- fides/ui-build/static/admin/poc/form-experiments/FormikAntFormItem.html +1 -1
- fides/ui-build/static/admin/poc/form-experiments/FormikControlled.html +1 -1
- fides/ui-build/static/admin/poc/form-experiments/FormikField.html +1 -1
- fides/ui-build/static/admin/poc/form-experiments/FormikSpreadField.html +1 -1
- fides/ui-build/static/admin/poc/forms.html +1 -1
- fides/ui-build/static/admin/poc/table-migration.html +1 -1
- fides/ui-build/static/admin/privacy-requests/[id].html +1 -1
- fides/ui-build/static/admin/privacy-requests/configure/messaging.html +1 -1
- fides/ui-build/static/admin/privacy-requests/configure/storage.html +1 -1
- fides/ui-build/static/admin/privacy-requests/configure.html +1 -1
- fides/ui-build/static/admin/privacy-requests.html +1 -1
- fides/ui-build/static/admin/properties/[id].html +1 -1
- fides/ui-build/static/admin/properties/add-property.html +1 -1
- fides/ui-build/static/admin/properties.html +1 -1
- fides/ui-build/static/admin/reporting/datamap.html +1 -1
- fides/ui-build/static/admin/settings/about/alpha.html +1 -1
- fides/ui-build/static/admin/settings/about.html +1 -1
- fides/ui-build/static/admin/settings/consent/[configuration_id]/[purpose_id].html +1 -1
- fides/ui-build/static/admin/settings/consent.html +1 -1
- fides/ui-build/static/admin/settings/custom-fields.html +1 -1
- fides/ui-build/static/admin/settings/domain-records.html +1 -1
- fides/ui-build/static/admin/settings/domains.html +1 -1
- fides/ui-build/static/admin/settings/email-templates.html +1 -1
- fides/ui-build/static/admin/settings/locations.html +1 -1
- fides/ui-build/static/admin/settings/organization.html +1 -1
- fides/ui-build/static/admin/settings/regulations.html +1 -1
- fides/ui-build/static/admin/systems/configure/[id]/test-datasets.html +1 -1
- fides/ui-build/static/admin/systems/configure/[id].html +1 -1
- fides/ui-build/static/admin/systems.html +1 -1
- fides/ui-build/static/admin/taxonomy.html +1 -1
- fides/ui-build/static/admin/user-management/new.html +1 -1
- fides/ui-build/static/admin/user-management/profile/[id].html +1 -1
- fides/ui-build/static/admin/user-management.html +1 -1
- fides/api/alembic/migrations/versions/41a634d8c669_manual_task_restrict_deletes.py +0 -257
- fides/api/alembic/migrations/versions/6a76a1fa4f3f_add_manual_task_instance_table.py +0 -256
- fides/api/alembic/migrations/versions/aadfe83c5644_add_manual_task_to_connectiontype_enum.py +0 -46
- fides/api/api/v1/endpoints/partitioning_endpoints.py +0 -108
- fides/api/models/manual_task.py +0 -965
- fides/api/schemas/partitioning/__init__.py +0 -17
- fides/api/schemas/partitioning/bigquery_time_based_partitioning.py +0 -31
- fides/api/schemas/partitioning/time_based_partitioning.py +0 -1376
- fides/ui-build/static/admin/_next/static/chunks/1169-76bbada4f3d16538.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/1807-3beab149351d5ded.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/3615-5e2d062d684b8fa1.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/4121-de4ca969faf2b9f4.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/570-c99f07161bd339cd.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/6084-40d5d94561a6093e.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/6662-6a915300505fd9c0.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/7476-aaf8970dbbbe4864.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/7630-c558dc3a199a633d.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/787-9c751615f5816094.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/827-c6fe34fb336467ae.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/9014-eeae6f581158e645.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/9767-1dca308466dce863.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/9826-303b14ef4fc7ab4a.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/add-systems-a8e0bc7b6674f47e.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/new-55243db34cf77b7e.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection-cdb77886d7fd4f44.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/integrations-40a3cd14264796e2.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/ant-components-3f62dd959a039fe9.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/table-migration-7852aa60090c8c9a.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-11dd6152bf6607cc.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-c50c2ee7d7d2a585.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-282de19599d67aaf.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-3f962ade5df86380.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-0a87f29768425a37.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/domains-b9e77c75c6b77c88.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/email-templates-bb60c397a03558d8.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/organization-4b835393f5274379.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/test-datasets-9669fa6b20545530.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-c9510a1eb612323d.js +0 -1
- fides/ui-build/static/admin/_next/static/ezJVaZ_Oi_0J2-wPEOvj1/_buildManifest.js +0 -1
- {ethyca_fides-2.64.3b0.dist-info → ethyca_fides-2.64.5rc3.dist-info}/WHEEL +0 -0
- {ethyca_fides-2.64.3b0.dist-info → ethyca_fides-2.64.5rc3.dist-info}/entry_points.txt +0 -0
- {ethyca_fides-2.64.3b0.dist-info → ethyca_fides-2.64.5rc3.dist-info}/licenses/LICENSE +0 -0
- {ethyca_fides-2.64.3b0.dist-info → ethyca_fides-2.64.5rc3.dist-info}/top_level.txt +0 -0
- /fides/ui-build/static/admin/_next/static/{ezJVaZ_Oi_0J2-wPEOvj1 → g740PFm_oIYCWNhoD6-r0}/_ssgManifest.js +0 -0
fides/api/models/manual_task.py
DELETED
|
@@ -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
|
-
)
|