ethyca-fides 2.64.5rc1__py2.py3-none-any.whl → 2.64.6b0__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.
- {ethyca_fides-2.64.5rc1.dist-info → ethyca_fides-2.64.6b0.dist-info}/METADATA +3 -3
- {ethyca_fides-2.64.5rc1.dist-info → ethyca_fides-2.64.6b0.dist-info}/RECORD +237 -246
- fides/_version.py +3 -3
- fides/api/alembic/migrations/versions/41a634d8c669_manual_task_restrict_deletes.py +257 -0
- fides/api/alembic/migrations/versions/6a76a1fa4f3f_add_manual_task_instance_table.py +256 -0
- fides/api/alembic/migrations/versions/aadfe83c5644_add_manual_task_to_connectiontype_enum.py +46 -0
- fides/api/api/v1/api.py +2 -0
- fides/api/api/v1/endpoints/partitioning_endpoints.py +108 -0
- fides/api/db/base.py +6 -3
- fides/api/db/database.py +27 -2
- fides/api/graph/config.py +16 -9
- fides/api/models/attachment.py +15 -3
- fides/api/models/comment.py +23 -5
- fides/api/models/connectionconfig.py +11 -0
- 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 +27 -2
- fides/api/models/manual_task.py +965 -0
- fides/api/models/tcf_publisher_restrictions.py +16 -4
- fides/api/schemas/partitioning/__init__.py +17 -0
- fides/api/schemas/partitioning/bigquery_time_based_partitioning.py +31 -0
- fides/api/schemas/partitioning/time_based_partitioning.py +1376 -0
- fides/api/service/connectors/query_configs/bigquery_query_config.py +44 -22
- fides/api/service/connectors/query_configs/query_config.py +5 -2
- fides/api/util/connection_util.py +25 -2
- fides/common/api/v1/urn_registry.py +4 -0
- fides/ui-build/static/admin/404.html +1 -1
- fides/ui-build/static/admin/_next/static/7-nocO64klVotMrKmugnq/_buildManifest.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{1040-c1c1372a7f909aef.js → 1040-d246ed641088a416.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/1169-ae67fde0c6d69abc.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/1807-3beab149351d5ded.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{1817-96182c1558f80b63.js → 1817-60f08a3619b9139c.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{2921-f5608275555bd7d9.js → 2921-85515257dd94ef4d.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{3450-272f26c102f3510d.js → 3450-4e472b9e2754fa47.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/3615-5e2d062d684b8fa1.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{3855-beb58821d1ddba89.js → 3855-2d045674fbf72a3c.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{3872-82482e55e69b5a93.js → 3872-056ddf3ed9d10b51.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{3923-a54c286a2ba0a47a.js → 3923-257df982a95371b5.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{401-d2ce0a5a9120e056.js → 401-3f2160e3910d075b.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{409-86f4f687105917fb.js → 409-3e2248a63dd60e58.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/4121-10bfa009892586fa.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{4230-63abbdfb9e9016b9.js → 4230-38c6e446801a8729.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{431-77d59d43e90058ca.js → 431-13b0ef67d5a3df2f.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{5309-10f68cf805817cfb.js → 5309-fd8cd5aedd45f7c1.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{5574-b6db9d62362e72d9.js → 5574-028ef28c3cf16995.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/570-c99f07161bd339cd.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/6084-fa1c82d03f6c256a.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/6662-d8ae12f69d325004.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{6853-8a1b8e1c8b249f2f.js → 6853-2644f28976b46c25.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{6882-6c94583bffe85ba7.js → 6882-ea071425d25dd2b0.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{6954-dc3540389daf94da.js → 6954-bb360fb60aac9440.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/7476-7073ec015f84a3e0.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/7630-302a13c63f9bfb45.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/787-b393c03ade9d93dc.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{79-26ccd45dfd6653a7.js → 79-b67ba449b0f2cc9c.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{796-38c0f7e6755ad359.js → 796-b7608f09607288b8.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/827-c6fe34fb336467ae.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/9014-eeae6f581158e645.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{9046-bbce3c73af16daf9.js → 9046-ece5efe762b810cb.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{905-742074a074be1055.js → 905-ffdbd0b14167e8bd.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{9226-5e0ce31cfdedd5ee.js → 9226-c9111590692341b1.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{9392.25024e070026343d.js → 9392.9a948112de74781b.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{9676.e60a53f1f5890847.js → 9676.cc515c853b8cf578.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/9767-277a0229aae7662a.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/9826-82c473dcaf892d00.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/{9951-d3d5d0fe4c4edb86.js → 9951-dbd76d7f3a7f1b9a.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{404-d41660858638adee.js → 404-ef01376efb8427e1.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{_app-6b3539f8d82ce9ae.js → _app-1650bbc3cb8c2299.js} +92 -89
- fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{manual-7c5e1e845372c99b.js → manual-4057c399f58d331e.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{multiple-87e78f52af21c4a9.js → multiple-2726ca51f0327347.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/add-systems-a2457d5da25aa854.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure/{add-vendors-6374a3a7747df964.js → add-vendors-9fe46ed10a7e7a1a.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/{configure-0512151e2ed0f4c1.js → configure-095828301f22cdaa.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{[id]-09435f4ab2deafd2.js → [id]-de60a5b74f6b20ff.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{new-a0039f216fb3eb93.js → new-06bb3b0bf097fcdb.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-experience-cd036518b5d4efbe.js → privacy-experience-1ee05fd0bc012ec6.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{[id]-0e534580abf670be.js → [id]-5a2e61c7d88bdda1.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{new-bb1790eb87b63109.js → new-1bc69669215fa55c.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-notices-67e9846f877a3f38.js → privacy-notices-fa8394d2e1072aba.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/{properties-69a92b6ddbc2bae2.js → properties-213c5405e9e4219c.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/consent/{reporting-d07d05f4b898a5ed.js → reporting-44aa77149d71a6fe.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{consent-23e886d692ab6d1a.js → consent-23ab7bd613a0ad53.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]/{[resourceUrn]-c623d6f1a61c8ea9.js → [resourceUrn]-11d52f1570759c4d.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/{[projectUrn]-6c766c766dc97c5c.js → [projectUrn]-dae11464a091537f.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{projects-28937a8da3d73145.js → projects-7442023478422295.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/resources/{[resourceUrn]-57bd5cdf784f059f.js → [resourceUrn]-b83afa5565d0c84e.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{resources-51d99174c8006eb5.js → resources-d8db234a44a2ddf4.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{data-catalog-627fbf19dce88e81.js → data-catalog-5597d2e691313bb0.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/{[systemId]-ed1629b05519a370.js → [systemId]-da06d05d255d0cd0.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/{[monitorId]-ad307bfc5f51fd9d.js → [monitorId]-895591fe32af0f4c.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{action-center-07cbd61ede6e18ac.js → action-center-a932a39e29ac3489.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{activity-6a2aaed8d0e66d82.js → activity-2cfdf4d55a7594ba.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/detection/{[resourceUrn]-06edce289876dea1.js → [resourceUrn]-393e20924c83373e.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{detection-faf326a6200637d0.js → detection-8733807dad4bc96e.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/discovery/{[resourceUrn]-64acf269256ee74f.js → [resourceUrn]-14bd7500362ff224.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{discovery-8c3e4be6d36da66d.js → discovery-9e7dfd5a6acc2e8f.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{datamap-b576a94b583a7940.js → datamap-07881d1a5fc03d41.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/{[...subfieldNames]-4912858ffde4621a.js → [...subfieldNames]-57be9d40c67b0acb.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/{[collectionName]-df21dd7ca0f35718.js → [collectionName]-bd78d6c6264e2467.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/{[datasetId]-5ce28a329e8f667f.js → [datasetId]-3c9103487b55e76f.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/new-e30a546a8cfb6658.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/{dataset-c6fab547396df6ac.js → dataset-500610c0b60f9e7e.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{[id]-d04c9925d324eee1.js → [id]-34958fe8183d9479.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{new-656abd09ea5ee39a.js → new-761294dbaf59bbe1.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection-59abd36059863e05.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/{index-b66687e8194495a2.js → index-ae100a873eb66d59.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-8eee4d0314c83e50.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/integrations-bf3b87b0dd702551.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{[id]-b74db8488e2e4b58.js → [id]-2aada2c7b9156053.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{add-template-a607018ff097b6c2.js → add-template-fbb7b0c43dedf072.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{messaging-4a1a04c5179d2053.js → messaging-7230d7ee21368cef.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/{ant-components-1567c9770a5f05aa.js → ant-components-7c234412502f8102.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{AntForm-4949fe7f1815462b.js → AntForm-72791aab60f3a4bf.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikAntFormItem-6085f73850302d55.js → FormikAntFormItem-da7d11d6146fa746.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikControlled-a3158e8217c13850.js → FormikControlled-3045d24344e99017.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikField-8576f1ef5c67d87d.js → FormikField-5b5b165d3f41a1de.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/{forms-341e67462b5e3352.js → forms-3afd8b6ba6234366.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/table-migration-52d50286216bcb8c.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-ee8d27e2f17563a0.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-535b6e5003d892eb.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-7ded688a1e832c63.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/{configure-d24230b890b13762.js → configure-08e0863d432b3348.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-7d625b170911a072.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/properties/{[id]-2bedc5013e13ab52.js → [id]-b8dcb1f5213521ef.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/properties/{add-property-9d68bd70299dd945.js → add-property-7d8418bb7cb9e1fd.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{properties-c3116b6bfe2e695e.js → properties-537003822f360ae7.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/reporting/{datamap-6dfa7091b99d8321.js → datamap-ac25749935da453b.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/about/{alpha-9751059905bba190.js → alpha-647d59bb0aa060bf.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/{about-ad29d77012ec9dba.js → about-73adc03fe0182e3f.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent/[configuration_id]/{[purpose_id]-32e3190c1ad00b40.js → [purpose_id]-ffa9e9e79ad75828.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-4fb6c8c4bd9cdb3f.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/{custom-fields-d2c0aac32f5d2930.js → custom-fields-94c1b7bfc6cec4d2.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domain-records-a10674380f94d014.js → domain-records-e9838b8e49e64e57.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/domains-0de16778ad2f8865.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/email-templates-aac71677024210ad.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/{locations-cc7d629433fa6d44.js → locations-f43e238571b21643.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/organization-f5e0a34f6ae473ad.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/{regulations-64a813cb2741683b.js → regulations-05d3c86ca3ca4d5d.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/test-datasets-31fcf7b52d8028b0.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/{[id]-fb3d094e4f4585f6.js → [id]-6db01a1afe2f82d5.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{systems-c2df5b7b0596a9cb.js → systems-8ec7472a7032301f.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-84caae0fc02f8ae1.js +1 -0
- fides/ui-build/static/admin/_next/static/chunks/pages/user-management/{new-b124cc24b930c9e1.js → new-a2524414e968f862.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/{[id]-fd2ff6b13052c54e.js → [id]-e452541827698b1f.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/{user-management-fa052b0439920ef6.js → user-management-530be849391d2425.js} +1 -1
- fides/ui-build/static/admin/_next/static/chunks/{webpack-e61d457474e00565.js → webpack-e25ccaae1ef867a2.js} +1 -1
- fides/ui-build/static/admin/_next/static/css/23391a3311f80cfe.css +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/models/manual_tasks/__init__.py +0 -14
- fides/api/models/manual_tasks/manual_task.py +0 -120
- fides/api/models/manual_tasks/manual_task_config.py +0 -136
- fides/api/models/manual_tasks/manual_task_log.py +0 -104
- fides/api/schemas/manual_tasks/__init__.py +0 -0
- fides/api/schemas/manual_tasks/manual_task_config.py +0 -311
- fides/api/schemas/manual_tasks/manual_task_schemas.py +0 -79
- fides/api/schemas/manual_tasks/manual_task_status.py +0 -151
- fides/service/manual_tasks/__init__.py +0 -0
- fides/service/manual_tasks/manual_task_config_service.py +0 -370
- fides/service/manual_tasks/manual_task_service.py +0 -294
- fides/service/manual_tasks/utils.py +0 -185
- fides/ui-build/static/admin/_next/static/chunks/1100-3fdbdf211c3c2a5b.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/2430-b480401d44c55416.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/3505-192986c86dc47869.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/3513-a563133845dc990f.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/3670-2abd9b2f17770872.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/3983-17ae9c232bddc413.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/4060-3486b45081151b69.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/4121-f0aecb2abd384945.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/4481-d181a9db72984adf.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/6060-cb1ab5be7067bf7b.js +0 -4
- fides/ui-build/static/admin/_next/static/chunks/6277-ccdb50f676a1b336.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/6659-b2088f525bf13c17.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/6662-42940a2b00933e79.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/69-943b19d39da339d9.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/7553-e7ae268701f3dcfe.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/8433-1e065c55c8da73b0.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/9767-96ed554a043c3c4d.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/c78d26b1-88a3e1bacb2a03c2.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/add-systems-68955d8441e60668.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/dataset/new-5287c76ecf600281.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection-23fbec0590c8d192.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-906bc5f05702efb0.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/integrations-024a1facb9be04d0.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/poc/table-migration-6f0e64f0c52bd68f.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-6971c7773dbf9b51.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-303bd2182da03088.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-831572cc7f42615f.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-569ff31eff637034.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-13a17a4ace7293d1.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/domains-78449b0e02bced88.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/email-templates-7d299c4cb3199036.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/settings/organization-a9fa55c40fa570a6.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/test-datasets-547b0cfe1e49e6d2.js +0 -1
- fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-261deb6fb3e51cb3.js +0 -1
- fides/ui-build/static/admin/_next/static/css/c693338e3bc8dcc6.css +0 -1
- fides/ui-build/static/admin/_next/static/css/e458b5f1afdbb7fc.css +0 -1
- fides/ui-build/static/admin/_next/static/wyqNbL8A-USLbXV5z1vV0/_buildManifest.js +0 -1
- {ethyca_fides-2.64.5rc1.dist-info → ethyca_fides-2.64.6b0.dist-info}/WHEEL +0 -0
- {ethyca_fides-2.64.5rc1.dist-info → ethyca_fides-2.64.6b0.dist-info}/entry_points.txt +0 -0
- {ethyca_fides-2.64.5rc1.dist-info → ethyca_fides-2.64.6b0.dist-info}/licenses/LICENSE +0 -0
- {ethyca_fides-2.64.5rc1.dist-info → ethyca_fides-2.64.6b0.dist-info}/top_level.txt +0 -0
- /fides/ui-build/static/admin/_next/static/{wyqNbL8A-USLbXV5z1vV0 → 7-nocO64klVotMrKmugnq}/_ssgManifest.js +0 -0
|
@@ -1,370 +0,0 @@
|
|
|
1
|
-
from typing import Any, Optional
|
|
2
|
-
|
|
3
|
-
from loguru import logger
|
|
4
|
-
from sqlalchemy.orm import Query, Session, selectinload
|
|
5
|
-
|
|
6
|
-
from fides.api.models.manual_tasks.manual_task import ManualTask
|
|
7
|
-
from fides.api.models.manual_tasks.manual_task_config import (
|
|
8
|
-
ManualTaskConfig,
|
|
9
|
-
ManualTaskConfigField,
|
|
10
|
-
)
|
|
11
|
-
from fides.api.schemas.manual_tasks.manual_task_config import (
|
|
12
|
-
ManualTaskConfigResponse,
|
|
13
|
-
ManualTaskConfigurationType,
|
|
14
|
-
)
|
|
15
|
-
from fides.service.manual_tasks.utils import validate_fields, with_task_logging
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class ManualTaskConfigService:
|
|
19
|
-
def __init__(self, db: Session):
|
|
20
|
-
self.db = db
|
|
21
|
-
|
|
22
|
-
def _create_log_data(
|
|
23
|
-
self, task_id: str, config_id: Optional[str], details: dict[str, Any]
|
|
24
|
-
) -> dict[str, Any]:
|
|
25
|
-
"""Create standard log data structure."""
|
|
26
|
-
return {"task_id": task_id, "config_id": config_id, "details": details}
|
|
27
|
-
|
|
28
|
-
def _get_base_config_query(self) -> Query:
|
|
29
|
-
"""Get base config query with field definitions loaded."""
|
|
30
|
-
return self.db.query(ManualTaskConfig).options(
|
|
31
|
-
selectinload(ManualTaskConfig.field_definitions)
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
def _create_config_version(
|
|
35
|
-
self,
|
|
36
|
-
task: ManualTask,
|
|
37
|
-
config_type: str,
|
|
38
|
-
version: int,
|
|
39
|
-
is_current: bool = True,
|
|
40
|
-
) -> ManualTaskConfig:
|
|
41
|
-
"""Create a new config version. This is a helper method that creates a new config
|
|
42
|
-
version and sets it as the current version.
|
|
43
|
-
|
|
44
|
-
Args:
|
|
45
|
-
task: The task to create the config for
|
|
46
|
-
config_type: The type of config to create
|
|
47
|
-
version: The version number of the config
|
|
48
|
-
is_current: Whether the config is the current version
|
|
49
|
-
Returns:
|
|
50
|
-
The new config
|
|
51
|
-
"""
|
|
52
|
-
try:
|
|
53
|
-
ManualTaskConfigurationType(config_type)
|
|
54
|
-
except ValueError:
|
|
55
|
-
raise ValueError(f"Invalid config type: {config_type}")
|
|
56
|
-
|
|
57
|
-
# Set all existing versions to non-current
|
|
58
|
-
if is_current:
|
|
59
|
-
self.db.query(ManualTaskConfig).filter(
|
|
60
|
-
ManualTaskConfig.task_id == task.id,
|
|
61
|
-
ManualTaskConfig.config_type == config_type,
|
|
62
|
-
).update({"is_current": False})
|
|
63
|
-
self.db.flush()
|
|
64
|
-
|
|
65
|
-
return ManualTaskConfig.create(
|
|
66
|
-
db=self.db,
|
|
67
|
-
data={
|
|
68
|
-
"task_id": task.id,
|
|
69
|
-
"config_type": config_type,
|
|
70
|
-
"version": version,
|
|
71
|
-
"is_current": is_current,
|
|
72
|
-
},
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
def _handle_field_updates(
|
|
76
|
-
self,
|
|
77
|
-
config: ManualTaskConfig,
|
|
78
|
-
field_updates: Optional[list[dict[str, Any]]] = None,
|
|
79
|
-
fields_to_remove: Optional[list[str]] = None,
|
|
80
|
-
previous_config: Optional[ManualTaskConfig] = None,
|
|
81
|
-
) -> set[str]:
|
|
82
|
-
"""Handle field updates, removals, and recreation from previous version. This is a helper
|
|
83
|
-
function that:
|
|
84
|
-
- Creates new fields from field_updates
|
|
85
|
-
- Recreates unmodified fields from previous version so they will remain in the config
|
|
86
|
-
- Removes fields that are no longer in the config
|
|
87
|
-
|
|
88
|
-
Args:
|
|
89
|
-
config: The config to update
|
|
90
|
-
field_updates: The fields to update
|
|
91
|
-
fields_to_remove: The fields to remove
|
|
92
|
-
previous_config: The previous config
|
|
93
|
-
Returns:
|
|
94
|
-
The modified keys
|
|
95
|
-
"""
|
|
96
|
-
modified_keys = set(fields_to_remove or [])
|
|
97
|
-
|
|
98
|
-
if field_updates:
|
|
99
|
-
validate_fields(field_updates, is_submission=False)
|
|
100
|
-
fields_to_create = [
|
|
101
|
-
{
|
|
102
|
-
"task_id": config.task_id,
|
|
103
|
-
"config_id": config.id,
|
|
104
|
-
"field_key": f["field_key"],
|
|
105
|
-
"field_type": f.get("field_type"),
|
|
106
|
-
"field_metadata": f.get("field_metadata", {}),
|
|
107
|
-
}
|
|
108
|
-
for f in field_updates
|
|
109
|
-
]
|
|
110
|
-
if fields_to_create:
|
|
111
|
-
self.db.bulk_insert_mappings(ManualTaskConfigField, fields_to_create)
|
|
112
|
-
modified_keys.update(f["field_key"] for f in field_updates)
|
|
113
|
-
|
|
114
|
-
if previous_config:
|
|
115
|
-
# Recreate unmodified fields from previous version
|
|
116
|
-
unmodified = [
|
|
117
|
-
{
|
|
118
|
-
"task_id": config.task_id,
|
|
119
|
-
"config_id": config.id,
|
|
120
|
-
"field_key": f.field_key,
|
|
121
|
-
"field_type": f.field_type,
|
|
122
|
-
"field_metadata": f.field_metadata,
|
|
123
|
-
}
|
|
124
|
-
for f in previous_config.field_definitions
|
|
125
|
-
if f.field_key not in modified_keys
|
|
126
|
-
]
|
|
127
|
-
if unmodified:
|
|
128
|
-
self.db.bulk_insert_mappings(ManualTaskConfigField, unmodified)
|
|
129
|
-
|
|
130
|
-
self.db.flush()
|
|
131
|
-
return modified_keys
|
|
132
|
-
|
|
133
|
-
def to_response(self, config: ManualTaskConfig) -> ManualTaskConfigResponse:
|
|
134
|
-
"""Convert config model to response object."""
|
|
135
|
-
return ManualTaskConfigResponse.model_validate(
|
|
136
|
-
{
|
|
137
|
-
"id": config.id,
|
|
138
|
-
"task_id": config.task_id,
|
|
139
|
-
"config_type": config.config_type,
|
|
140
|
-
"version": config.version,
|
|
141
|
-
"is_current": config.is_current,
|
|
142
|
-
"fields": [
|
|
143
|
-
{
|
|
144
|
-
"field_key": f.field_key,
|
|
145
|
-
"field_type": f.field_type,
|
|
146
|
-
"field_metadata": f.field_metadata,
|
|
147
|
-
}
|
|
148
|
-
for f in config.field_definitions
|
|
149
|
-
],
|
|
150
|
-
"created_at": config.created_at,
|
|
151
|
-
"updated_at": config.updated_at,
|
|
152
|
-
}
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
def get_current_config(
|
|
156
|
-
self, task: ManualTask, config_type: str
|
|
157
|
-
) -> ManualTaskConfig:
|
|
158
|
-
"""Get current config for task by type."""
|
|
159
|
-
config = (
|
|
160
|
-
self._get_base_config_query()
|
|
161
|
-
.filter(
|
|
162
|
-
ManualTaskConfig.task_id == task.id,
|
|
163
|
-
ManualTaskConfig.config_type == config_type,
|
|
164
|
-
ManualTaskConfig.is_current.is_(True),
|
|
165
|
-
)
|
|
166
|
-
.first()
|
|
167
|
-
)
|
|
168
|
-
|
|
169
|
-
if not config:
|
|
170
|
-
raise ValueError(
|
|
171
|
-
f"No current config found for task {task.id} and type {config_type}"
|
|
172
|
-
)
|
|
173
|
-
return config
|
|
174
|
-
|
|
175
|
-
def list_config_type_versions(
|
|
176
|
-
self, task: ManualTask, config_type: str
|
|
177
|
-
) -> list[ManualTaskConfig]:
|
|
178
|
-
"""List all versions of a config type for a task."""
|
|
179
|
-
return (
|
|
180
|
-
self._get_base_config_query()
|
|
181
|
-
.filter(
|
|
182
|
-
ManualTaskConfig.task_id == task.id,
|
|
183
|
-
ManualTaskConfig.config_type == config_type,
|
|
184
|
-
)
|
|
185
|
-
.order_by(ManualTaskConfig.version.desc())
|
|
186
|
-
.all()
|
|
187
|
-
)
|
|
188
|
-
|
|
189
|
-
def get_config(
|
|
190
|
-
self,
|
|
191
|
-
task: ManualTask,
|
|
192
|
-
config_type: str,
|
|
193
|
-
field_id: str,
|
|
194
|
-
config_id: str,
|
|
195
|
-
field_key: str,
|
|
196
|
-
version: int,
|
|
197
|
-
) -> Optional[ManualTaskConfig]:
|
|
198
|
-
"""Get config by various filters. This is a flexible lookup method that can find configs based on various filters.
|
|
199
|
-
|
|
200
|
-
Args:
|
|
201
|
-
task: The task to get the config for
|
|
202
|
-
config_type: The type of config to get
|
|
203
|
-
field_id: The ID of a field in the config
|
|
204
|
-
config_id: The ID of the config
|
|
205
|
-
field_key: The key of a field in the config
|
|
206
|
-
version: The version number of the config
|
|
207
|
-
Returns:
|
|
208
|
-
The matching config if found, None otherwise
|
|
209
|
-
"""
|
|
210
|
-
if not any([task, config_id, field_id, config_type]):
|
|
211
|
-
logger.debug("No filters provided to get_config")
|
|
212
|
-
return None
|
|
213
|
-
|
|
214
|
-
query = self._get_base_config_query()
|
|
215
|
-
if field_id or field_key:
|
|
216
|
-
query = query.join(ManualTaskConfig.field_definitions)
|
|
217
|
-
|
|
218
|
-
filters = [
|
|
219
|
-
f
|
|
220
|
-
for f in [
|
|
221
|
-
task and ManualTaskConfig.task_id == task.id,
|
|
222
|
-
config_id and ManualTaskConfig.id == config_id,
|
|
223
|
-
field_id and ManualTaskConfigField.id == field_id,
|
|
224
|
-
field_key and ManualTaskConfigField.field_key == field_key,
|
|
225
|
-
version and ManualTaskConfig.version == version,
|
|
226
|
-
config_type and ManualTaskConfig.config_type == config_type,
|
|
227
|
-
]
|
|
228
|
-
if f
|
|
229
|
-
]
|
|
230
|
-
|
|
231
|
-
return query.filter(*filters).first()
|
|
232
|
-
|
|
233
|
-
@with_task_logging("Creating new configuration version")
|
|
234
|
-
def create_new_version(
|
|
235
|
-
self,
|
|
236
|
-
task: ManualTask,
|
|
237
|
-
config_type: str,
|
|
238
|
-
field_updates: Optional[list[dict[str, Any]]] = None,
|
|
239
|
-
fields_to_remove: Optional[list[str]] = None,
|
|
240
|
-
previous_config: Optional[ManualTaskConfig] = None,
|
|
241
|
-
) -> tuple[ManualTaskConfig, dict[str, Any]]:
|
|
242
|
-
"""Create new version of configuration.
|
|
243
|
-
|
|
244
|
-
Args:
|
|
245
|
-
task: The task to create the config for
|
|
246
|
-
config_type: The type of config to create
|
|
247
|
-
field_updates: The fields to update
|
|
248
|
-
fields_to_remove: The fields to remove
|
|
249
|
-
previous_config: The previous config
|
|
250
|
-
|
|
251
|
-
Returns:
|
|
252
|
-
Tuple containing the new config and log data, the log data is
|
|
253
|
-
captured by the with_task_logging decorator. and the new config is
|
|
254
|
-
returned to the caller.
|
|
255
|
-
"""
|
|
256
|
-
new_config = self._create_config_version(
|
|
257
|
-
task, config_type, (previous_config.version + 1 if previous_config else 1)
|
|
258
|
-
)
|
|
259
|
-
|
|
260
|
-
self._handle_field_updates(
|
|
261
|
-
new_config, field_updates, fields_to_remove, previous_config
|
|
262
|
-
)
|
|
263
|
-
|
|
264
|
-
return new_config, self._create_log_data(
|
|
265
|
-
task.id,
|
|
266
|
-
new_config.id,
|
|
267
|
-
{
|
|
268
|
-
"config_type": config_type,
|
|
269
|
-
"version": new_config.version,
|
|
270
|
-
"added_field_keys": [f.get("field_key") for f in (field_updates or [])],
|
|
271
|
-
"removed_field_keys": fields_to_remove or [],
|
|
272
|
-
},
|
|
273
|
-
)
|
|
274
|
-
|
|
275
|
-
@with_task_logging("Adding fields to configuration")
|
|
276
|
-
def add_fields(
|
|
277
|
-
self, task: ManualTask, config_type: str, fields: list[dict[str, Any]]
|
|
278
|
-
) -> tuple[ManualTaskConfig, dict[str, Any]]:
|
|
279
|
-
"""Add fields to configuration.
|
|
280
|
-
|
|
281
|
-
Args:
|
|
282
|
-
task: The task to add the fields to
|
|
283
|
-
config_type: The type of config to add the fields to
|
|
284
|
-
fields: The fields to add
|
|
285
|
-
|
|
286
|
-
Returns:
|
|
287
|
-
Tuple containing the new config and log data, the log data is
|
|
288
|
-
captured by the with_task_logging decorator. and the new config is
|
|
289
|
-
returned to the caller.
|
|
290
|
-
"""
|
|
291
|
-
current = self.get_current_config(task, config_type)
|
|
292
|
-
self.create_new_version(task, config_type, fields, previous_config=current)
|
|
293
|
-
new_config = self.get_current_config(task, config_type)
|
|
294
|
-
|
|
295
|
-
return new_config, self._create_log_data(
|
|
296
|
-
task.id,
|
|
297
|
-
current.id,
|
|
298
|
-
{
|
|
299
|
-
"config_type": config_type,
|
|
300
|
-
"previous_version": current.version,
|
|
301
|
-
"added_field_keys": [f.get("field_key") for f in fields],
|
|
302
|
-
"new_config_id": new_config.id,
|
|
303
|
-
"new_config_version": new_config.version,
|
|
304
|
-
},
|
|
305
|
-
)
|
|
306
|
-
|
|
307
|
-
@with_task_logging("Removing fields from configuration")
|
|
308
|
-
def remove_fields(
|
|
309
|
-
self, task: ManualTask, config_type: str, field_keys: list[str]
|
|
310
|
-
) -> tuple[ManualTaskConfig, dict[str, Any]]:
|
|
311
|
-
"""Remove fields from configuration.
|
|
312
|
-
|
|
313
|
-
Args:
|
|
314
|
-
task: The task to remove the fields from
|
|
315
|
-
config_type: The type of config to remove the fields from
|
|
316
|
-
field_keys: The keys of the fields to remove
|
|
317
|
-
|
|
318
|
-
Returns:
|
|
319
|
-
Tuple containing the new config and log data, the log data is
|
|
320
|
-
captured by the with_task_logging decorator. and the new config is
|
|
321
|
-
returned to the caller.
|
|
322
|
-
"""
|
|
323
|
-
current = self.get_current_config(task, config_type)
|
|
324
|
-
self.create_new_version(
|
|
325
|
-
task, config_type, fields_to_remove=field_keys, previous_config=current
|
|
326
|
-
)
|
|
327
|
-
new_config = self.get_current_config(task, config_type)
|
|
328
|
-
|
|
329
|
-
return new_config, self._create_log_data(
|
|
330
|
-
task.id,
|
|
331
|
-
current.id,
|
|
332
|
-
{
|
|
333
|
-
"config_type": config_type,
|
|
334
|
-
"version": current.version,
|
|
335
|
-
"deleted_field_keys": field_keys,
|
|
336
|
-
"new_config_id": new_config.id,
|
|
337
|
-
"new_config_version": new_config.version,
|
|
338
|
-
},
|
|
339
|
-
)
|
|
340
|
-
|
|
341
|
-
@with_task_logging("Deleting Manual Task configuration")
|
|
342
|
-
def delete_config(
|
|
343
|
-
self, task: ManualTask, config_id: str
|
|
344
|
-
) -> tuple[ManualTaskConfig, dict[str, Any]]:
|
|
345
|
-
"""Delete config for task.
|
|
346
|
-
|
|
347
|
-
Args:
|
|
348
|
-
task: The task to delete the config for
|
|
349
|
-
config_id: The ID of the config to delete
|
|
350
|
-
|
|
351
|
-
Returns:
|
|
352
|
-
Tuple containing the deleted config and log data, the log data is
|
|
353
|
-
captured by the with_task_logging decorator. and the deleted config is
|
|
354
|
-
returned to the caller.
|
|
355
|
-
"""
|
|
356
|
-
config = self.db.query(ManualTaskConfig).filter_by(id=config_id).first()
|
|
357
|
-
if not config:
|
|
358
|
-
raise ValueError(f"Config with ID {config_id} not found")
|
|
359
|
-
|
|
360
|
-
log_data = self._create_log_data(
|
|
361
|
-
task.id,
|
|
362
|
-
None,
|
|
363
|
-
{
|
|
364
|
-
"config_type": config.config_type,
|
|
365
|
-
"version": config.version,
|
|
366
|
-
"deleted_config_id": config_id,
|
|
367
|
-
},
|
|
368
|
-
)
|
|
369
|
-
config.delete(self.db)
|
|
370
|
-
return config, log_data
|
|
@@ -1,294 +0,0 @@
|
|
|
1
|
-
from typing import Any, Optional, cast
|
|
2
|
-
|
|
3
|
-
from loguru import logger
|
|
4
|
-
from sqlalchemy import select
|
|
5
|
-
from sqlalchemy.orm import Session
|
|
6
|
-
|
|
7
|
-
from fides.api.models.fides_user import FidesUser
|
|
8
|
-
from fides.api.models.manual_tasks.manual_task import ManualTask, ManualTaskReference
|
|
9
|
-
from fides.api.models.manual_tasks.manual_task_config import ManualTaskConfig
|
|
10
|
-
from fides.api.schemas.manual_tasks.manual_task_schemas import (
|
|
11
|
-
ManualTaskParentEntityType,
|
|
12
|
-
ManualTaskReferenceType,
|
|
13
|
-
ManualTaskType,
|
|
14
|
-
)
|
|
15
|
-
from fides.service.manual_tasks.manual_task_config_service import (
|
|
16
|
-
ManualTaskConfigService,
|
|
17
|
-
)
|
|
18
|
-
from fides.service.manual_tasks.utils import with_task_logging
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class ManualTaskService:
|
|
22
|
-
def __init__(self, db: Session):
|
|
23
|
-
self.db = db
|
|
24
|
-
self.config_service = ManualTaskConfigService(db)
|
|
25
|
-
|
|
26
|
-
def get_task(
|
|
27
|
-
self,
|
|
28
|
-
task_id: Optional[str] = None,
|
|
29
|
-
parent_entity_id: Optional[str] = None,
|
|
30
|
-
parent_entity_type: Optional[ManualTaskParentEntityType] = None,
|
|
31
|
-
task_type: Optional[ManualTaskType] = None,
|
|
32
|
-
) -> ManualTask:
|
|
33
|
-
"""Get the manual task using provided filters.
|
|
34
|
-
|
|
35
|
-
This is a flexible lookup method that can find tasks based on various filters.
|
|
36
|
-
It's normal for this method to return None if no task matches the given filters.
|
|
37
|
-
|
|
38
|
-
Args:
|
|
39
|
-
task_id: The task ID
|
|
40
|
-
parent_entity_id: The parent entity ID
|
|
41
|
-
parent_entity_type: The parent entity type
|
|
42
|
-
task_type: The task type
|
|
43
|
-
|
|
44
|
-
Returns:
|
|
45
|
-
ManualTask: The matching task
|
|
46
|
-
"""
|
|
47
|
-
if not any([task_id, parent_entity_id, parent_entity_type, task_type]):
|
|
48
|
-
logger.debug("No filters provided to get_task")
|
|
49
|
-
raise ValueError("No filters provided to get_task")
|
|
50
|
-
|
|
51
|
-
# Build filter conditions and a human-readable description
|
|
52
|
-
filters = []
|
|
53
|
-
filter_desc = []
|
|
54
|
-
if task_id:
|
|
55
|
-
filters.append(ManualTask.id == task_id)
|
|
56
|
-
filter_desc.append(f"task_id={task_id}")
|
|
57
|
-
if parent_entity_id:
|
|
58
|
-
filters.append(ManualTask.parent_entity_id == parent_entity_id)
|
|
59
|
-
filter_desc.append(f"parent_entity_id={parent_entity_id}")
|
|
60
|
-
if parent_entity_type:
|
|
61
|
-
filters.append(ManualTask.parent_entity_type == parent_entity_type)
|
|
62
|
-
filter_desc.append(f"parent_entity_type={parent_entity_type}")
|
|
63
|
-
if task_type:
|
|
64
|
-
filters.append(ManualTask.task_type == task_type)
|
|
65
|
-
filter_desc.append(f"task_type={task_type}")
|
|
66
|
-
|
|
67
|
-
# Apply all filters at once
|
|
68
|
-
stmt = select(ManualTask) # type: ignore[arg-type]
|
|
69
|
-
if filters:
|
|
70
|
-
stmt = stmt.where(*filters)
|
|
71
|
-
|
|
72
|
-
task = self.db.execute(stmt).scalar_one_or_none()
|
|
73
|
-
if task is None:
|
|
74
|
-
logger.debug(f"No task found with filters: {filter_desc}")
|
|
75
|
-
raise ValueError(f"No task found with filters: {filter_desc}")
|
|
76
|
-
return task
|
|
77
|
-
|
|
78
|
-
@with_task_logging("Provided user IDs verified")
|
|
79
|
-
def _non_existent_users(
|
|
80
|
-
self, non_existent_user_ids: list[str], *, task_id: str
|
|
81
|
-
) -> None:
|
|
82
|
-
"""This is a helper function to raise an error if users do not exist.
|
|
83
|
-
If non_existent_user_ids is empty, this function will instead create
|
|
84
|
-
a success log entry.
|
|
85
|
-
|
|
86
|
-
Args:
|
|
87
|
-
non_existent_user_ids: List of non-existent user IDs
|
|
88
|
-
task_id: The task ID
|
|
89
|
-
|
|
90
|
-
Returns:
|
|
91
|
-
None
|
|
92
|
-
"""
|
|
93
|
-
if len(non_existent_user_ids) > 0:
|
|
94
|
-
raise ValueError(
|
|
95
|
-
f"User(s) {sorted(list(non_existent_user_ids))} do not exist"
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
def _create_log_data(self, task_id: str, details: dict[str, Any]) -> dict[str, Any]:
|
|
99
|
-
"""Create standard log data structure.
|
|
100
|
-
|
|
101
|
-
Args:
|
|
102
|
-
task_id: The task ID
|
|
103
|
-
details: The log details
|
|
104
|
-
|
|
105
|
-
Returns:
|
|
106
|
-
dict: The log data structure
|
|
107
|
-
"""
|
|
108
|
-
return {
|
|
109
|
-
"task_id": task_id,
|
|
110
|
-
"details": details,
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
def _handle_user_errors(
|
|
114
|
-
self,
|
|
115
|
-
non_existent_users: list[str],
|
|
116
|
-
task_id: str,
|
|
117
|
-
details: dict[str, Any],
|
|
118
|
-
success_count: int,
|
|
119
|
-
error_key: str,
|
|
120
|
-
) -> None:
|
|
121
|
-
"""Handle errors for non-existent users.
|
|
122
|
-
|
|
123
|
-
Args:
|
|
124
|
-
non_existent_users: List of non-existent user IDs
|
|
125
|
-
task_id: The task ID
|
|
126
|
-
details: The log details to update
|
|
127
|
-
success_count: Number of successful operations
|
|
128
|
-
error_key: Key to use for error details
|
|
129
|
-
|
|
130
|
-
Raises:
|
|
131
|
-
ValueError: If no successful operations and users don't exist
|
|
132
|
-
"""
|
|
133
|
-
try:
|
|
134
|
-
self._non_existent_users(non_existent_users, task_id=task_id)
|
|
135
|
-
except ValueError as e:
|
|
136
|
-
details[error_key] = sorted(non_existent_users)
|
|
137
|
-
if success_count == 0:
|
|
138
|
-
raise e
|
|
139
|
-
|
|
140
|
-
def _get_existing_users(self, user_ids: list[str]) -> set[str]:
|
|
141
|
-
"""Get set of existing user IDs from the provided list.
|
|
142
|
-
|
|
143
|
-
Args:
|
|
144
|
-
user_ids: List of user IDs to check
|
|
145
|
-
|
|
146
|
-
Returns:
|
|
147
|
-
set: Set of existing user IDs
|
|
148
|
-
"""
|
|
149
|
-
return set(
|
|
150
|
-
user.id
|
|
151
|
-
for user in self.db.query(FidesUser)
|
|
152
|
-
.filter(FidesUser.id.in_(user_ids))
|
|
153
|
-
.all()
|
|
154
|
-
)
|
|
155
|
-
|
|
156
|
-
def _handle_user_operation(
|
|
157
|
-
self,
|
|
158
|
-
task_id: str,
|
|
159
|
-
user_ids: list[str],
|
|
160
|
-
operation_type: str,
|
|
161
|
-
current_users: Optional[set[str]] = None,
|
|
162
|
-
) -> tuple[set[str], dict[str, Any]]:
|
|
163
|
-
"""Handle user assignment/unassignment operations.
|
|
164
|
-
|
|
165
|
-
Args:
|
|
166
|
-
task_id: The task ID
|
|
167
|
-
user_ids: List of user IDs to process
|
|
168
|
-
operation_type: Type of operation ('assign' or 'unassign')
|
|
169
|
-
current_users: Optional set of current users
|
|
170
|
-
|
|
171
|
-
Returns:
|
|
172
|
-
tuple: (processed_users, log_data)
|
|
173
|
-
"""
|
|
174
|
-
if not (user_ids := list(set(user_ids))):
|
|
175
|
-
raise ValueError(f"User ID is required for {operation_type}ment")
|
|
176
|
-
|
|
177
|
-
existing_users = set(
|
|
178
|
-
u.id
|
|
179
|
-
for u in self.db.query(FidesUser).filter(FidesUser.id.in_(user_ids)).all()
|
|
180
|
-
)
|
|
181
|
-
processed_users = (
|
|
182
|
-
existing_users - (current_users or set())
|
|
183
|
-
if operation_type == "assign"
|
|
184
|
-
else existing_users
|
|
185
|
-
)
|
|
186
|
-
details = {f"{operation_type}ed_users": sorted(list(processed_users))}
|
|
187
|
-
|
|
188
|
-
if non_existing := list(set(user_ids) - existing_users):
|
|
189
|
-
try:
|
|
190
|
-
self._non_existent_users(non_existing, task_id=task_id)
|
|
191
|
-
except ValueError as e:
|
|
192
|
-
details[f"user_ids_not_{operation_type}ed"] = sorted(non_existing)
|
|
193
|
-
if not processed_users:
|
|
194
|
-
raise e
|
|
195
|
-
|
|
196
|
-
return processed_users, {"task_id": task_id, "details": details}
|
|
197
|
-
|
|
198
|
-
@with_task_logging("Assign users to task")
|
|
199
|
-
def assign_users_to_task(
|
|
200
|
-
self, task_id: str, user_ids: list[str]
|
|
201
|
-
) -> tuple[ManualTask, dict[str, Any]]:
|
|
202
|
-
"""Assign users to a task.
|
|
203
|
-
|
|
204
|
-
Args:
|
|
205
|
-
task_id: The task ID
|
|
206
|
-
user_ids: List of user IDs to assign
|
|
207
|
-
|
|
208
|
-
Returns:
|
|
209
|
-
Tuple containing the task and log data, the log data is
|
|
210
|
-
captured by the with_task_logging decorator. and the task is
|
|
211
|
-
returned to the caller.
|
|
212
|
-
"""
|
|
213
|
-
task = self.get_task(task_id=task_id)
|
|
214
|
-
users_to_assign, log_data = self._handle_user_operation(
|
|
215
|
-
task_id, user_ids, "assign", set(task.assigned_users)
|
|
216
|
-
)
|
|
217
|
-
|
|
218
|
-
if users_to_assign:
|
|
219
|
-
self.db.bulk_insert_mappings(
|
|
220
|
-
ManualTaskReference,
|
|
221
|
-
[
|
|
222
|
-
{
|
|
223
|
-
"task_id": task.id,
|
|
224
|
-
"reference_id": user_id,
|
|
225
|
-
"reference_type": ManualTaskReferenceType.assigned_user,
|
|
226
|
-
}
|
|
227
|
-
for user_id in users_to_assign
|
|
228
|
-
],
|
|
229
|
-
)
|
|
230
|
-
self.db.flush()
|
|
231
|
-
self.db.refresh(task)
|
|
232
|
-
|
|
233
|
-
return task, log_data
|
|
234
|
-
|
|
235
|
-
@with_task_logging("Unassign users from task")
|
|
236
|
-
def unassign_users_from_task(
|
|
237
|
-
self, task_id: str, user_ids: list[str]
|
|
238
|
-
) -> tuple[ManualTask, dict[str, Any]]:
|
|
239
|
-
task = self.get_task(task_id=task_id)
|
|
240
|
-
refs_to_unassign = (
|
|
241
|
-
self.db.query(ManualTaskReference)
|
|
242
|
-
.filter(
|
|
243
|
-
ManualTaskReference.task_id == task.id,
|
|
244
|
-
ManualTaskReference.reference_type
|
|
245
|
-
== ManualTaskReferenceType.assigned_user,
|
|
246
|
-
ManualTaskReference.reference_id.in_(user_ids),
|
|
247
|
-
)
|
|
248
|
-
.all()
|
|
249
|
-
)
|
|
250
|
-
|
|
251
|
-
if refs_to_unassign:
|
|
252
|
-
self.db.query(ManualTaskReference).filter(
|
|
253
|
-
ManualTaskReference.id.in_([ref.id for ref in refs_to_unassign])
|
|
254
|
-
).delete(synchronize_session=False)
|
|
255
|
-
self.db.flush()
|
|
256
|
-
self.db.refresh(task)
|
|
257
|
-
|
|
258
|
-
_, log_data = self._handle_user_operation(task_id, user_ids, "unassign")
|
|
259
|
-
return task, log_data
|
|
260
|
-
|
|
261
|
-
def create_config(
|
|
262
|
-
self, config_type: str, fields: list[dict], task_id: str
|
|
263
|
-
) -> ManualTaskConfig:
|
|
264
|
-
"""Create a new config for a task.
|
|
265
|
-
|
|
266
|
-
Args:
|
|
267
|
-
config_type: The config type
|
|
268
|
-
fields: The fields for the config
|
|
269
|
-
task_id: The task ID
|
|
270
|
-
|
|
271
|
-
Returns:
|
|
272
|
-
ManualTaskConfig: The new config
|
|
273
|
-
"""
|
|
274
|
-
task = self.get_task(task_id=task_id)
|
|
275
|
-
config = self.config_service.create_new_version(task, config_type, fields)
|
|
276
|
-
return cast(ManualTaskConfig, config)
|
|
277
|
-
|
|
278
|
-
def delete_config(self, config: ManualTaskConfig, task_id: str) -> None:
|
|
279
|
-
"""Delete this configuration.
|
|
280
|
-
Args:
|
|
281
|
-
config: The config to delete
|
|
282
|
-
task_id: The task ID
|
|
283
|
-
Raises:
|
|
284
|
-
ValueError: If there are active instances using this configuration
|
|
285
|
-
ValueError: If the task does not exist
|
|
286
|
-
|
|
287
|
-
Returns:
|
|
288
|
-
dict[str, Any]: The log details - intercepted by the `with_task_logging` decorator.
|
|
289
|
-
"""
|
|
290
|
-
task = self.get_task(task_id=task_id)
|
|
291
|
-
|
|
292
|
-
# Delete the configuration
|
|
293
|
-
config_id = config.id
|
|
294
|
-
self.config_service.delete_config(task, config_id)
|