diff --git a/api/main/rest/_attribute_query.py b/api/main/rest/_attribute_query.py index 6f06f454f..4aa87667b 100644 --- a/api/main/rest/_attribute_query.py +++ b/api/main/rest/_attribute_query.py @@ -103,7 +103,7 @@ def _get_info_for_attribute(project, entity_type, key): if key.startswith('$'): if key in ['$x', '$y', '$u', '$v', '$width', '$height', '$fps']: return {'name': key[1:], 'dtype': 'float'} - elif key in ['$version', '$user', '$type', '$created_by', '$modified_by', '$frame', '$num_frames', '$section']: + elif key in ['$version', '$user', '$type', '$created_by', '$modified_by', '$frame', '$num_frames', '$section', '$id']: return {'name': key[1:], 'dtype': 'int'} elif key in ['$created_datetime', '$modified_datetime']: return {'name': key[1:], 'dtype': 'datetime'} @@ -244,11 +244,13 @@ def build_query_recursively(query_object, castLookup, is_media, project): distance, lat, lon = value value = (Point(float(lon),float(lat), srid=4326), Distance(km=float(distance)), 'spheroid') - castFunc = castLookup[attr_name] + castFunc = castLookup.get(attr_name,None) if operation in ['isnull']: value = _convert_boolean(value) elif castFunc: value = castFunc(value) + else: + return Q(pk=-1) if operation in ['date_eq','eq']: query = Q(**{f"{db_lookup}": value}) else: diff --git a/api/main/rest/_util.py b/api/main/rest/_util.py index 1bace2df8..155e5d298 100644 --- a/api/main/rest/_util.py +++ b/api/main/rest/_util.py @@ -341,9 +341,16 @@ def bulk_log_creation(objects, project, user): def construct_elemental_id_from_parent(parent, requested_uuid=None): """ Return the parent's elemental id or make a new one """ - if parent is None and requested_uuid is None: - return uuid.uuid4() - elif parent.elemental_id: + if parent and hasattr(parent, "elemental_id") and parent.elemental_id: return parent.elemental_id - else: - return None + if requested_uuid: + # Check to see if it is a UUID or string and treat accordingly + if type(requested_uuid) == uuid.UUID: + return requested_uuid + if type(requested_uuid) == str: + try: + return uuid.UUID(requested_uuid) + except Exception: + logger.error(f"Could not convert '%s' into a UUID", str(requested_uuid)) + raise + return uuid.uuid4() diff --git a/api/main/rest/localization.py b/api/main/rest/localization.py index a4f149f69..9fa1b5688 100644 --- a/api/main/rest/localization.py +++ b/api/main/rest/localization.py @@ -232,6 +232,8 @@ def _patch(self, params): entity_type = obj.type new_attrs = validate_attributes(params, qs[0]) update_kwargs = {"modified_by": self.request.user} + if params.get("new_elemental_id", None) is not None: + update_kwargs["elemental_id"] = params["new_elemental_id"] if params.get('user_elemental_id', None): computed_author = compute_user(params['project'], self.request.user, params.get('user_elemental_id', None)) update_kwargs['created_by'] = computed_author diff --git a/api/main/schema/components/localization.py b/api/main/schema/components/localization.py index 4942ae03a..1ef7d6bfe 100644 --- a/api/main/schema/components/localization.py +++ b/api/main/schema/components/localization.py @@ -292,6 +292,10 @@ 'type': 'integer', 'description': 'Unique integer identifying a new version for these objects', }, + "new_elemental_id": { + "description": "The new elemental ID for these objects", + "type": "string", + }, 'user_elemental_id': { 'description': 'Unique ID of the original user who created this. If permissions allow, will change the creating user to the one referenced by this elemental_id', 'type': 'string' diff --git a/api/main/search.py b/api/main/search.py index 5c2efbef2..99b7f72b2 100644 --- a/api/main/search.py +++ b/api/main/search.py @@ -42,10 +42,12 @@ def _get_unique_index_name(entity_type, attribute): entity_name_sanitized=re.sub(r"[^a-zA-Z0-9]","_",entity_type.name).lower() attribute_name_sanitized=re.sub(r"[^a-zA-Z0-9]","_",attribute['name']).lower() if attribute['name'].startswith('$'): + # Native fields are only scoped to project, native-string types are project/type bound + # Both need to incorporate type name in the name for uniqueness. if attribute['dtype'] == 'native': - index_name=f"tator_proj_{entity_type.project.id}_internal_{attribute_name_sanitized}" + index_name=f"tator_proj_{entity_type.project.id}_{type_name_sanitized}_internalv2_{attribute_name_sanitized}" else: - index_name=f"tator_proj_{entity_type.project.id}_{type_name_sanitized}_internal_{attribute_name_sanitized}" + index_name=f"tator_proj_{entity_type.project.id}_{type_name_sanitized}_internalv2_{entity_name_sanitized}_{attribute_name_sanitized}" else: index_name=f"tator_proj_{entity_type.project.id}_{type_name_sanitized}_{entity_name_sanitized}_{attribute_name_sanitized}" return index_name