ethyca-fides 2.68.1b1__py2.py3-none-any.whl → 2.68.1b2__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ethyca-fides might be problematic. Click here for more details.

Files changed (116) hide show
  1. {ethyca_fides-2.68.1b1.dist-info → ethyca_fides-2.68.1b2.dist-info}/METADATA +1 -1
  2. {ethyca_fides-2.68.1b1.dist-info → ethyca_fides-2.68.1b2.dist-info}/RECORD +113 -105
  3. fides/_version.py +3 -3
  4. fides/api/alembic/migrations/versions/3baf42d251a6_add_generic_taxonomy_models.py +239 -0
  5. fides/api/api/v1/endpoints/generic_overrides.py +64 -167
  6. fides/api/db/base.py +6 -0
  7. fides/api/models/taxonomy.py +275 -0
  8. fides/api/service/deps.py +5 -0
  9. fides/api/service/privacy_request/request_service.py +6 -1
  10. fides/api/task/manual/manual_task_graph_task.py +11 -0
  11. fides/api/util/connection_type.py +68 -33
  12. fides/data/sample_project/docker-compose.yml +3 -3
  13. fides/service/taxonomy/__init__.py +0 -0
  14. fides/service/taxonomy/handlers/__init__.py +11 -0
  15. fides/service/taxonomy/handlers/base.py +42 -0
  16. fides/service/taxonomy/handlers/legacy_handler.py +95 -0
  17. fides/service/taxonomy/taxonomy_service.py +261 -0
  18. fides/service/taxonomy/utils.py +160 -0
  19. fides/ui-build/static/admin/404.html +1 -1
  20. fides/ui-build/static/admin/_next/static/chunks/pages/{_app-65723cd4b8fc36ac.js → _app-2c10f6b217b7978b.js} +1 -1
  21. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-58827eb86516931f.js +1 -0
  22. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/{[id]-766e57bcf38b5b1e.js → [id]-4e286a1e501a0c73.js} +1 -1
  23. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-709bcb0bc6a5382d.js +1 -0
  24. fides/ui-build/static/admin/_next/static/css/a72179b1754aadd3.css +1 -0
  25. fides/ui-build/static/admin/_next/static/{tzF4yti8NslASlGnxnZ8m → qvk5eMANVfwYkdURE7fgG}/_buildManifest.js +1 -1
  26. fides/ui-build/static/admin/add-systems/manual.html +1 -1
  27. fides/ui-build/static/admin/add-systems/multiple.html +1 -1
  28. fides/ui-build/static/admin/add-systems.html +1 -1
  29. fides/ui-build/static/admin/consent/configure/add-vendors.html +1 -1
  30. fides/ui-build/static/admin/consent/configure.html +1 -1
  31. fides/ui-build/static/admin/consent/privacy-experience/[id].html +1 -1
  32. fides/ui-build/static/admin/consent/privacy-experience/new.html +1 -1
  33. fides/ui-build/static/admin/consent/privacy-experience.html +1 -1
  34. fides/ui-build/static/admin/consent/privacy-notices/[id].html +1 -1
  35. fides/ui-build/static/admin/consent/privacy-notices/new.html +1 -1
  36. fides/ui-build/static/admin/consent/privacy-notices.html +1 -1
  37. fides/ui-build/static/admin/consent/properties.html +1 -1
  38. fides/ui-build/static/admin/consent/reporting.html +1 -1
  39. fides/ui-build/static/admin/consent.html +1 -1
  40. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn].html +1 -1
  41. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn].html +1 -1
  42. fides/ui-build/static/admin/data-catalog/[systemId]/projects.html +1 -1
  43. fides/ui-build/static/admin/data-catalog/[systemId]/resources/[resourceUrn].html +1 -1
  44. fides/ui-build/static/admin/data-catalog/[systemId]/resources.html +1 -1
  45. fides/ui-build/static/admin/data-catalog.html +1 -1
  46. fides/ui-build/static/admin/data-discovery/action-center/[monitorId]/[systemId].html +1 -1
  47. fides/ui-build/static/admin/data-discovery/action-center/[monitorId].html +1 -1
  48. fides/ui-build/static/admin/data-discovery/action-center.html +1 -1
  49. fides/ui-build/static/admin/data-discovery/activity.html +1 -1
  50. fides/ui-build/static/admin/data-discovery/detection/[resourceUrn].html +1 -1
  51. fides/ui-build/static/admin/data-discovery/detection.html +1 -1
  52. fides/ui-build/static/admin/data-discovery/discovery/[resourceUrn].html +1 -1
  53. fides/ui-build/static/admin/data-discovery/discovery.html +1 -1
  54. fides/ui-build/static/admin/datamap.html +1 -1
  55. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName]/[...subfieldNames].html +1 -1
  56. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName].html +1 -1
  57. fides/ui-build/static/admin/dataset/[datasetId].html +1 -1
  58. fides/ui-build/static/admin/dataset/new.html +1 -1
  59. fides/ui-build/static/admin/dataset.html +1 -1
  60. fides/ui-build/static/admin/datastore-connection/[id].html +1 -1
  61. fides/ui-build/static/admin/datastore-connection/new.html +1 -1
  62. fides/ui-build/static/admin/datastore-connection.html +1 -1
  63. fides/ui-build/static/admin/index.html +1 -1
  64. fides/ui-build/static/admin/integrations/[id].html +1 -1
  65. fides/ui-build/static/admin/integrations.html +1 -1
  66. fides/ui-build/static/admin/lib/fides-preview.js +1 -1
  67. fides/ui-build/static/admin/lib/fides-tcf.js +2 -2
  68. fides/ui-build/static/admin/lib/fides.js +1 -1
  69. fides/ui-build/static/admin/login/[provider].html +1 -1
  70. fides/ui-build/static/admin/login.html +1 -1
  71. fides/ui-build/static/admin/messaging/[id].html +1 -1
  72. fides/ui-build/static/admin/messaging/add-template.html +1 -1
  73. fides/ui-build/static/admin/messaging.html +1 -1
  74. fides/ui-build/static/admin/poc/ant-components.html +1 -1
  75. fides/ui-build/static/admin/poc/form-experiments/AntForm.html +1 -1
  76. fides/ui-build/static/admin/poc/form-experiments/FormikAntFormItem.html +1 -1
  77. fides/ui-build/static/admin/poc/form-experiments/FormikControlled.html +1 -1
  78. fides/ui-build/static/admin/poc/form-experiments/FormikField.html +1 -1
  79. fides/ui-build/static/admin/poc/form-experiments/FormikSpreadField.html +1 -1
  80. fides/ui-build/static/admin/poc/forms.html +1 -1
  81. fides/ui-build/static/admin/poc/table-migration.html +1 -1
  82. fides/ui-build/static/admin/privacy-requests/[id].html +1 -1
  83. fides/ui-build/static/admin/privacy-requests/configure/messaging.html +1 -1
  84. fides/ui-build/static/admin/privacy-requests/configure/storage.html +1 -1
  85. fides/ui-build/static/admin/privacy-requests/configure.html +1 -1
  86. fides/ui-build/static/admin/privacy-requests.html +1 -1
  87. fides/ui-build/static/admin/properties/[id].html +1 -1
  88. fides/ui-build/static/admin/properties/add-property.html +1 -1
  89. fides/ui-build/static/admin/properties.html +1 -1
  90. fides/ui-build/static/admin/reporting/datamap.html +1 -1
  91. fides/ui-build/static/admin/settings/about/alpha.html +1 -1
  92. fides/ui-build/static/admin/settings/about.html +1 -1
  93. fides/ui-build/static/admin/settings/consent/[configuration_id]/[purpose_id].html +1 -1
  94. fides/ui-build/static/admin/settings/consent.html +1 -1
  95. fides/ui-build/static/admin/settings/custom-fields.html +1 -1
  96. fides/ui-build/static/admin/settings/domain-records.html +1 -1
  97. fides/ui-build/static/admin/settings/domains.html +1 -1
  98. fides/ui-build/static/admin/settings/email-templates.html +1 -1
  99. fides/ui-build/static/admin/settings/locations.html +1 -1
  100. fides/ui-build/static/admin/settings/organization.html +1 -1
  101. fides/ui-build/static/admin/settings/regulations.html +1 -1
  102. fides/ui-build/static/admin/systems/configure/[id]/test-datasets.html +1 -1
  103. fides/ui-build/static/admin/systems/configure/[id].html +1 -1
  104. fides/ui-build/static/admin/systems.html +1 -1
  105. fides/ui-build/static/admin/taxonomy.html +1 -1
  106. fides/ui-build/static/admin/user-management/new.html +1 -1
  107. fides/ui-build/static/admin/user-management/profile/[id].html +1 -1
  108. fides/ui-build/static/admin/user-management.html +1 -1
  109. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-53a763e49ce34a74.js +0 -1
  110. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-f43a988542813110.js +0 -1
  111. fides/ui-build/static/admin/_next/static/css/e1628f15dd5f019b.css +0 -1
  112. {ethyca_fides-2.68.1b1.dist-info → ethyca_fides-2.68.1b2.dist-info}/WHEEL +0 -0
  113. {ethyca_fides-2.68.1b1.dist-info → ethyca_fides-2.68.1b2.dist-info}/entry_points.txt +0 -0
  114. {ethyca_fides-2.68.1b1.dist-info → ethyca_fides-2.68.1b2.dist-info}/licenses/LICENSE +0 -0
  115. {ethyca_fides-2.68.1b1.dist-info → ethyca_fides-2.68.1b2.dist-info}/top_level.txt +0 -0
  116. /fides/ui-build/static/admin/_next/static/{tzF4yti8NslASlGnxnZ8m → qvk5eMANVfwYkdURE7fgG}/_ssgManifest.js +0 -0
@@ -0,0 +1,261 @@
1
+ """
2
+ Service layer for taxonomy management (data_categories, data_uses, data_subjects).
3
+ """
4
+
5
+ from typing import Any, Dict, List, Literal, Optional, Union, overload
6
+
7
+ from sqlalchemy import or_
8
+ from sqlalchemy.orm import Session
9
+
10
+ from fides.api.models.sql_models import ( # type:ignore[attr-defined]
11
+ DataCategory,
12
+ DataSubject,
13
+ DataUse,
14
+ )
15
+ from fides.api.models.taxonomy import TaxonomyUsage
16
+
17
+ from .handlers import LegacyTaxonomyHandler, TaxonomyHandler
18
+ from .utils import (
19
+ activate_taxonomy_parents,
20
+ check_for_taxonomy_reactivation,
21
+ deactivate_taxonomy_node_and_descendants,
22
+ generate_taxonomy_fides_key,
23
+ handle_taxonomy_reactivation,
24
+ validate_default_taxonomy_restrictions,
25
+ validate_parent_key_exists,
26
+ )
27
+
28
+
29
+ class TaxonomyService:
30
+ """
31
+ Taxonomy service for managing Fides taxonomy elements.
32
+ Provides CRUD operations for data_categories, data_uses, and data_subjects.
33
+ """
34
+
35
+ # Most of the main methods in this service have a type-specific overload to help with type hints
36
+
37
+ def __init__(self, db: Session):
38
+ self.db = db
39
+
40
+ @overload
41
+ def get_elements(
42
+ self,
43
+ taxonomy_type: Literal["data_categories"],
44
+ active_only: bool = True,
45
+ parent_key: Optional[str] = None,
46
+ ) -> List[DataCategory]: ...
47
+
48
+ @overload
49
+ def get_elements(
50
+ self,
51
+ taxonomy_type: Literal["data_uses"],
52
+ active_only: bool = True,
53
+ parent_key: Optional[str] = None,
54
+ ) -> List[DataUse]: ...
55
+
56
+ @overload
57
+ def get_elements(
58
+ self,
59
+ taxonomy_type: Literal["data_subjects"],
60
+ active_only: bool = True,
61
+ parent_key: Optional[str] = None,
62
+ ) -> List[DataSubject]: ...
63
+
64
+ def get_elements(
65
+ self,
66
+ taxonomy_type: str,
67
+ active_only: bool = True,
68
+ parent_key: Optional[str] = None,
69
+ ) -> List[Union[DataCategory, DataUse, DataSubject]]:
70
+ """Get elements for a taxonomy type."""
71
+ return self._get_handler(taxonomy_type).get_elements(active_only, parent_key)
72
+
73
+ @overload
74
+ def get_element(
75
+ self, taxonomy_type: Literal["data_categories"], fides_key: str
76
+ ) -> Optional[DataCategory]: ...
77
+
78
+ @overload
79
+ def get_element(
80
+ self, taxonomy_type: Literal["data_uses"], fides_key: str
81
+ ) -> Optional[DataUse]: ...
82
+
83
+ @overload
84
+ def get_element(
85
+ self, taxonomy_type: Literal["data_subjects"], fides_key: str
86
+ ) -> Optional[DataSubject]: ...
87
+
88
+ def get_element(self, taxonomy_type: str, fides_key: str) -> Optional[Any]:
89
+ """Get a single element by fides_key."""
90
+ return self._get_handler(taxonomy_type).get_element(fides_key)
91
+
92
+ @overload
93
+ def create_element(
94
+ self, taxonomy_type: Literal["data_categories"], element_data: Dict
95
+ ) -> DataCategory: ...
96
+
97
+ @overload
98
+ def create_element(
99
+ self, taxonomy_type: Literal["data_uses"], element_data: Dict
100
+ ) -> DataUse: ...
101
+
102
+ @overload
103
+ def create_element(
104
+ self, taxonomy_type: Literal["data_subjects"], element_data: Dict
105
+ ) -> DataSubject: ...
106
+
107
+ def create_element(
108
+ self, taxonomy_type: str, element_data: Dict
109
+ ) -> Union[DataCategory, DataUse, DataSubject]:
110
+ """Create a new taxonomy element."""
111
+ # Generate fides_key if not provided
112
+ processed_data = element_data.copy()
113
+ if not processed_data.get("fides_key") and processed_data.get("name"):
114
+ handler = self._get_handler(taxonomy_type)
115
+ processed_data["fides_key"] = generate_taxonomy_fides_key(
116
+ taxonomy_type,
117
+ processed_data["name"],
118
+ processed_data.get("parent_key"),
119
+ handler,
120
+ )
121
+
122
+ # Centralized validation before delegation
123
+ self._validate_element_data(processed_data, taxonomy_type, action="create")
124
+ return self._get_handler(taxonomy_type).create_element(processed_data)
125
+
126
+ @overload
127
+ def update_element(
128
+ self,
129
+ taxonomy_type: Literal["data_categories"],
130
+ fides_key: str,
131
+ element_data: Dict,
132
+ ) -> Optional[DataCategory]: ...
133
+
134
+ @overload
135
+ def update_element(
136
+ self, taxonomy_type: Literal["data_uses"], fides_key: str, element_data: Dict
137
+ ) -> Optional[DataUse]: ...
138
+
139
+ @overload
140
+ def update_element(
141
+ self,
142
+ taxonomy_type: Literal["data_subjects"],
143
+ fides_key: str,
144
+ element_data: Dict,
145
+ ) -> Optional[DataSubject]: ...
146
+
147
+ def update_element(
148
+ self, taxonomy_type: str, fides_key: str, element_data: Dict
149
+ ) -> Optional[Any]:
150
+ """Update an existing taxonomy element."""
151
+ # Get the existing element for validation
152
+ handler = self._get_handler(taxonomy_type)
153
+ existing_element = handler.get_element(fides_key)
154
+
155
+ self._validate_element_data(
156
+ element_data,
157
+ taxonomy_type,
158
+ existing_element=existing_element,
159
+ action="update",
160
+ )
161
+
162
+ # Update the element via handler
163
+ updated_element = handler.update_element(fides_key, element_data)
164
+
165
+ # Handle hierarchical activation/deactivation logic at service level
166
+ if updated_element and "active" in element_data:
167
+ if element_data["active"]:
168
+ activate_taxonomy_parents(updated_element, self.db)
169
+ else:
170
+ # Cascade down - deactivate current node and children
171
+ deactivate_taxonomy_node_and_descendants(updated_element, self.db)
172
+
173
+ # Ensure hierarchical updates are visible across sessions
174
+ # The model's own update() commits, but parent/child mutations above
175
+ # only flush by design. Commit here so other sessions (e.g., API tests)
176
+ # can observe the propagated changes immediately.
177
+ self.db.commit()
178
+ # Refresh the updated element to return the latest state
179
+ self.db.refresh(updated_element)
180
+
181
+ return updated_element
182
+
183
+ def delete_element(self, taxonomy_type: str, fides_key: str) -> None:
184
+ """Delete a taxonomy element."""
185
+ # First, remove any TaxonomyUsage rows that reference this element
186
+ # as either the source or the target element. There is no DB cascade
187
+ # for these relationships by design, so this cleanup is handled here.
188
+ self.db.query(TaxonomyUsage).filter(
189
+ or_(
190
+ TaxonomyUsage.source_element_key == fides_key,
191
+ TaxonomyUsage.target_element_key == fides_key,
192
+ )
193
+ ).delete(synchronize_session=False)
194
+
195
+ # Then delete the element itself via the appropriate handler
196
+ self._get_handler(taxonomy_type).delete_element(fides_key)
197
+ self.db.commit()
198
+
199
+ @overload
200
+ def create_or_update_element(
201
+ self, taxonomy_type: Literal["data_categories"], element_data: Dict
202
+ ) -> DataCategory: ...
203
+
204
+ @overload
205
+ def create_or_update_element(
206
+ self, taxonomy_type: Literal["data_uses"], element_data: Dict
207
+ ) -> DataUse: ...
208
+
209
+ @overload
210
+ def create_or_update_element(
211
+ self, taxonomy_type: Literal["data_subjects"], element_data: Dict
212
+ ) -> DataSubject: ...
213
+
214
+ def create_or_update_element(self, taxonomy_type: str, element_data: Dict) -> Any:
215
+ """
216
+ Create or update a taxonomy element.
217
+ If the element is deactivated, it will be updated and re-activated, along with its parents.
218
+ This method provides compatibility with the existing generic_overrides endpoint pattern.
219
+ """
220
+ # Check for reactivation case centrally
221
+ handler = self._get_handler(taxonomy_type)
222
+ reactivation_element = check_for_taxonomy_reactivation(
223
+ self.db, taxonomy_type, element_data, handler
224
+ )
225
+
226
+ if reactivation_element:
227
+ return handle_taxonomy_reactivation(
228
+ self.db, taxonomy_type, reactivation_element, element_data, handler
229
+ )
230
+
231
+ return self.create_element(taxonomy_type, element_data) # type: ignore[call-overload]
232
+
233
+ def _get_handler(self, taxonomy_type: str) -> TaxonomyHandler:
234
+ """Get the handler for taxonomy operations."""
235
+ return LegacyTaxonomyHandler(self.db, taxonomy_type)
236
+
237
+ def _validate_element_data(
238
+ self,
239
+ element_data: Dict,
240
+ taxonomy_type: str,
241
+ existing_element: Optional[Union[DataCategory, DataUse, DataSubject]] = None,
242
+ action: str = "create",
243
+ ) -> None:
244
+ """
245
+ Centralized validation for taxonomy elements.
246
+ This runs before delegation to ensure consistent validation across all handlers.
247
+ """
248
+ # Validate default taxonomy restrictions for taxonomy elements
249
+ if action == "create":
250
+ validate_default_taxonomy_restrictions(element_data, action="create")
251
+ elif action == "update" and existing_element:
252
+ validate_default_taxonomy_restrictions(
253
+ element_data, resource=existing_element, action="update"
254
+ )
255
+
256
+ # Validate parent_key exists if provided
257
+ if "parent_key" in element_data and element_data["parent_key"]:
258
+ handler = self._get_handler(taxonomy_type)
259
+ validate_parent_key_exists(
260
+ taxonomy_type, element_data["parent_key"], handler
261
+ )
@@ -0,0 +1,160 @@
1
+ from typing import Any, Dict, Optional, Union
2
+
3
+ from sqlalchemy.orm import Session
4
+
5
+ from fides.api.common_exceptions import ValidationError
6
+ from fides.api.db.base_class import get_key_from_data
7
+ from fides.api.models.sql_models import ( # type:ignore[attr-defined]
8
+ DataCategory,
9
+ DataSubject,
10
+ DataUse,
11
+ )
12
+ from fides.api.util.errors import ForbiddenIsDefaultTaxonomyError
13
+
14
+
15
+ # Core validation functions for taxonomy operations
16
+ def activate_taxonomy_parents(
17
+ resource: Union[DataCategory, DataUse, DataSubject],
18
+ db: Session,
19
+ ) -> None:
20
+ """
21
+ Activates parents to match newly-active taxonomy node.
22
+ """
23
+ parent = resource.parent
24
+ if parent:
25
+ parent.active = True
26
+ db.flush()
27
+ activate_taxonomy_parents(parent, db)
28
+
29
+
30
+ def deactivate_taxonomy_node_and_descendants(
31
+ resource: Union[DataCategory, DataUse, DataSubject],
32
+ db: Session,
33
+ ) -> None:
34
+ """
35
+ Recursively de-activates all descendants of a given taxonomy node.
36
+ """
37
+ resource.active = False
38
+ db.flush()
39
+ children = resource.children
40
+
41
+ for child in children:
42
+ # Deactivate current child
43
+ child.active = False
44
+ db.flush()
45
+ # Recursively deactivate all descendants of this child
46
+ deactivate_taxonomy_node_and_descendants(child, db)
47
+
48
+
49
+ def validate_default_taxonomy_restrictions(
50
+ data: Dict,
51
+ resource: Optional[Union[DataCategory, DataUse, DataSubject]] = None,
52
+ action: str = "create",
53
+ ) -> None:
54
+ """
55
+ Validate restrictions on default taxonomy elements.
56
+ """
57
+ # For creation, check if trying to create with is_default=True
58
+ if action == "create" and data.get("is_default"):
59
+ raise ForbiddenIsDefaultTaxonomyError(
60
+ "taxonomy", data.get("fides_key", "unknown"), action="create"
61
+ )
62
+
63
+ # For updates, check if trying to modify is_default field
64
+ if action == "update" and resource:
65
+ # Only check if is_default is explicitly present in the data and is being changed
66
+ if "is_default" in data and hasattr(resource, "is_default"):
67
+ if data["is_default"] != resource.is_default:
68
+ raise ForbiddenIsDefaultTaxonomyError(
69
+ "resource",
70
+ data.get("fides_key", resource.fides_key),
71
+ action="modify",
72
+ )
73
+
74
+
75
+ def validate_parent_key_exists(
76
+ taxonomy_type: str, parent_key: str, handler: Any
77
+ ) -> None:
78
+ """
79
+ Validate that the parent_key exists in the same taxonomy type.
80
+ This prevents IntegrityError at the database level by validating at application level.
81
+ """
82
+ if not parent_key:
83
+ return
84
+
85
+ parent_element = handler.get_element(parent_key)
86
+
87
+ if not parent_element:
88
+ raise ValidationError(
89
+ f"Parent with key '{parent_key}' not found in taxonomy '{taxonomy_type}'"
90
+ )
91
+
92
+
93
+ def generate_taxonomy_fides_key(
94
+ taxonomy_type: str,
95
+ name: str,
96
+ parent_key: Optional[str] = None,
97
+ handler: Optional[Any] = None,
98
+ ) -> str:
99
+ """
100
+ Generate a fides_key from a name for taxonomy elements.
101
+ """
102
+ # Get the actual model class name for key generation
103
+ if handler and hasattr(handler, "get_model"):
104
+ model_class = handler.get_model()
105
+ fides_key = get_key_from_data({"name": name}, model_class.__name__)
106
+ else:
107
+ # Fallback to using taxonomy_type
108
+ fides_key = get_key_from_data({"name": name}, taxonomy_type)
109
+
110
+ # Add parent prefix if this is not a root level taxonomy node
111
+ if parent_key:
112
+ fides_key = f"{parent_key}.{fides_key}"
113
+
114
+ return fides_key
115
+
116
+
117
+ def check_for_taxonomy_reactivation(
118
+ db: Session, taxonomy_type: str, element_data: Dict, handler: Any
119
+ ) -> Optional[Any]:
120
+ """
121
+ Check if this is a reactivation case for existing disabled elements.
122
+ Returns the disabled element if it exists and should be reactivated.
123
+ """
124
+ # Only check for reactivation if no fides_key is provided but name is
125
+ if element_data.get("fides_key") or not element_data.get("name"):
126
+ return None
127
+
128
+ # Check the specific model table for disabled elements
129
+ model_class = handler.get_model()
130
+ disabled_element = (
131
+ db.query(model_class)
132
+ .filter(
133
+ model_class.active.is_(False),
134
+ model_class.name == element_data["name"],
135
+ )
136
+ .first()
137
+ )
138
+ return disabled_element
139
+
140
+
141
+ def handle_taxonomy_reactivation(
142
+ db: Session, taxonomy_type: str, element: Any, element_data: Dict, handler: Any
143
+ ) -> Any:
144
+ """
145
+ Handle reactivation of a disabled taxonomy element.
146
+ """
147
+ # Generate fides_key if not provided (needed for reactivation)
148
+ updated_data = element_data.copy()
149
+ if not updated_data.get("fides_key") and updated_data.get("name"):
150
+ updated_data["fides_key"] = generate_taxonomy_fides_key(
151
+ taxonomy_type, updated_data["name"], updated_data.get("parent_key"), handler
152
+ )
153
+
154
+ # Ensure it's marked as active and activate parents accordingly
155
+ updated_data["active"] = True
156
+ activate_taxonomy_parents(element, db)
157
+
158
+ # Update the element with new data
159
+ element.update(db, data=updated_data)
160
+ return element
@@ -1 +1 @@
1
- <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link data-next-font="" rel="preconnect" href="/" crossorigin="anonymous"/><link rel="preload" href="/_next/static/css/e1628f15dd5f019b.css" as="style"/><link rel="stylesheet" href="/_next/static/css/e1628f15dd5f019b.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-69658aeaf6155d89.js" defer=""></script><script src="/_next/static/chunks/framework-c92fc3344e6fd165.js" defer=""></script><script src="/_next/static/chunks/main-090643377c8254e6.js" defer=""></script><script src="/_next/static/chunks/pages/_app-65723cd4b8fc36ac.js" defer=""></script><script src="/_next/static/chunks/pages/404-9174cdb70126c2c5.js" defer=""></script><script src="/_next/static/tzF4yti8NslASlGnxnZ8m/_buildManifest.js" defer=""></script><script src="/_next/static/tzF4yti8NslASlGnxnZ8m/_ssgManifest.js" defer=""></script><style>.data-ant-cssinjs-cache-path{content:"";}</style></head><body><div id="__next"><div style="height:100%;display:flex"></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/404","query":{},"buildId":"tzF4yti8NslASlGnxnZ8m","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link data-next-font="" rel="preconnect" href="/" crossorigin="anonymous"/><link rel="preload" href="/_next/static/css/a72179b1754aadd3.css" as="style"/><link rel="stylesheet" href="/_next/static/css/a72179b1754aadd3.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-69658aeaf6155d89.js" defer=""></script><script src="/_next/static/chunks/framework-c92fc3344e6fd165.js" defer=""></script><script src="/_next/static/chunks/main-090643377c8254e6.js" defer=""></script><script src="/_next/static/chunks/pages/_app-2c10f6b217b7978b.js" defer=""></script><script src="/_next/static/chunks/pages/404-9174cdb70126c2c5.js" defer=""></script><script src="/_next/static/qvk5eMANVfwYkdURE7fgG/_buildManifest.js" defer=""></script><script src="/_next/static/qvk5eMANVfwYkdURE7fgG/_ssgManifest.js" defer=""></script><style>.data-ant-cssinjs-cache-path{content:"";}</style></head><body><div id="__next"><div style="height:100%;display:flex"></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/404","query":{},"buildId":"qvk5eMANVfwYkdURE7fgG","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>