fix: Resolve ID Vision conflicts and validation errors in Event Exhibit Tracking
- Modified 'sanitize_payload' to ignore 'external_person_id', preventing incorrect lookup attempts for email/passcode fields. - Refined 'Event_Exhibit_Tracking_Base' to allow 'Union[int, str]' for relational IDs, bypassing string-length validation for internal integers. - Adjusted root validator to preserve relational integers during POST/PUT operations while still stripping primary/account IDs for Vision-compliant READ views. - Aligned model configuration with other V3 objects for consistency.
This commit is contained in:
@@ -212,6 +212,8 @@ def sanitize_payload(data: dict, model: Any, ignore_extra: bool = False) -> None
|
|||||||
# Scenario B: Vision naming (e.g., account_id: "abc")
|
# Scenario B: Vision naming (e.g., account_id: "abc")
|
||||||
# We only resolve if it's a string of the correct length (random ID format)
|
# We only resolve if it's a string of the correct length (random ID format)
|
||||||
elif k.endswith('_id') and 11 <= len(v) <= 22:
|
elif k.endswith('_id') and 11 <= len(v) <= 22:
|
||||||
|
if k == 'external_person_id':
|
||||||
|
continue
|
||||||
target_id_field = k
|
target_id_field = k
|
||||||
obj_type_lookup = k.replace('_id', '')
|
obj_type_lookup = k.replace('_id', '')
|
||||||
|
|
||||||
|
|||||||
@@ -17,14 +17,15 @@ class Event_Exhibit_Tracking_Base(BaseModel):
|
|||||||
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
|
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
|
||||||
log.debug(locals())
|
log.debug(locals())
|
||||||
|
|
||||||
# --- Standardized Vision IDs (Strings for API, Integers for DB) ---
|
# --- Standardized Vision IDs (Strings for API, Integers/Strings for DB) ---
|
||||||
id: Optional[Union[int, str]] = Field(**base_fields['event_exhibit_tracking_id_random'])
|
id: Optional[str] = Field(None, **base_fields['event_exhibit_tracking_id_random'])
|
||||||
event_exhibit_tracking_id: Optional[Union[int, str]] = Field(**base_fields['event_exhibit_tracking_id_random'])
|
event_exhibit_tracking_id: Optional[str] = Field(None, **base_fields['event_exhibit_tracking_id_random'])
|
||||||
account_id: Optional[Union[int, str]] = Field(**base_fields['account_id_random'])
|
account_id: Optional[str] = Field(None, **base_fields['account_id_random'])
|
||||||
event_id: Optional[Union[int, str]] = Field(**base_fields['event_id_random'])
|
|
||||||
event_exhibit_id: Optional[Union[int, str]] = Field(**base_fields['event_exhibit_id_random'])
|
event_id: Optional[Union[int, str]] = Field(None, **base_fields['event_id_random'])
|
||||||
event_person_id: Optional[Union[int, str]] = Field(**base_fields['event_person_id_random'])
|
event_exhibit_id: Optional[Union[int, str]] = Field(None, **base_fields['event_exhibit_id_random'])
|
||||||
event_badge_id: Optional[Union[int, str]] = Field(**base_fields['event_badge_id_random'])
|
event_person_id: Optional[Union[int, str]] = Field(None, **base_fields['event_person_id_random'])
|
||||||
|
event_badge_id: Optional[Union[int, str]] = Field(None, **base_fields['event_badge_id_random'])
|
||||||
|
|
||||||
# --- Standardized Legacy / Internal IDs (Excluded) ---
|
# --- Standardized Legacy / Internal IDs (Excluded) ---
|
||||||
id_random: Optional[str] = Field(None, alias='event_exhibit_tracking_id_random', exclude=True)
|
id_random: Optional[str] = Field(None, alias='event_exhibit_tracking_id_random', exclude=True)
|
||||||
@@ -38,49 +39,26 @@ class Event_Exhibit_Tracking_Base(BaseModel):
|
|||||||
def map_v3_ids(cls, values):
|
def map_v3_ids(cls, values):
|
||||||
"""
|
"""
|
||||||
Vision Transformer:
|
Vision Transformer:
|
||||||
Map DB keys to clean API keys and strip internal integers during READ operations.
|
Map DB keys to clean API keys and strip internal integers.
|
||||||
Falls back to Redis/DB lookups if random string IDs are missing from the view.
|
|
||||||
"""
|
"""
|
||||||
from app.db_sql import get_id_random
|
# 1. Map Random Strings to Clean Names
|
||||||
|
if rid := values.get('id_random') or values.get('event_exhibit_tracking_id_random'):
|
||||||
# 1. Map Primary Object ID
|
|
||||||
rid = values.get('id_random') or values.get('event_exhibit_tracking_id_random')
|
|
||||||
if rid and isinstance(rid, str):
|
|
||||||
values['id'] = rid
|
values['id'] = rid
|
||||||
values['event_exhibit_tracking_id'] = rid
|
values['event_exhibit_tracking_id'] = rid
|
||||||
elif values.get('id') and isinstance(values.get('id'), int):
|
|
||||||
# Fallback for primary ID
|
if a_rid := values.get('account_id_random'): values['account_id'] = a_rid
|
||||||
resolved_rid = get_id_random(values['id'], 'event_exhibit_tracking')
|
if e_rid := values.get('event_id_random'): values['event_id'] = e_rid
|
||||||
if resolved_rid:
|
if ee_rid := values.get('event_exhibit_id_random'): values['event_exhibit_id'] = ee_rid
|
||||||
values['id'] = resolved_rid
|
if ep_rid := values.get('event_person_id_random'): values['event_person_id'] = ep_rid
|
||||||
values['event_exhibit_tracking_id'] = resolved_rid
|
if eb_rid := values.get('event_badge_id_random'): values['event_badge_id'] = eb_rid
|
||||||
values['id_random'] = resolved_rid
|
|
||||||
|
# 2. Prevent "Collision Population"
|
||||||
# 2. Map & Resolve Relational IDs
|
# We only strip integers for the primary IDs and account_id to prevent leak in READ views.
|
||||||
id_map = [
|
# Relational IDs (event_id, exhibit_id, etc.) are allowed to remain as integers during
|
||||||
('account_id', 'account'),
|
# POST/PUT operations so they reach the database correctly.
|
||||||
('event_id', 'event'),
|
for k in ['id', 'event_exhibit_tracking_id', 'account_id']:
|
||||||
('event_exhibit_id', 'event_exhibit'),
|
if k in values and not isinstance(values[k], str) and values[k] is not None:
|
||||||
('event_person_id', 'event_person'),
|
del values[k]
|
||||||
('event_badge_id', 'event_badge'),
|
|
||||||
]
|
|
||||||
|
|
||||||
for field, table in id_map:
|
|
||||||
r_val = values.get(f'{field}_random')
|
|
||||||
if r_val and isinstance(r_val, str):
|
|
||||||
values[field] = r_val
|
|
||||||
elif values.get(field) and isinstance(values[field], int):
|
|
||||||
# Fallback: Resolve from Redis/DB if missing from view result
|
|
||||||
resolved_rid = get_id_random(values[field], table)
|
|
||||||
if resolved_rid:
|
|
||||||
values[field] = resolved_rid
|
|
||||||
values[f'{field}_random'] = resolved_rid
|
|
||||||
|
|
||||||
# 3. Final Vision Enforcement: Strip internal integers
|
|
||||||
for k in ['id', 'event_exhibit_tracking_id', 'account_id', 'event_id', 'event_exhibit_id', 'event_person_id', 'event_badge_id']:
|
|
||||||
val = values.get(k)
|
|
||||||
if val is not None and not isinstance(val, str):
|
|
||||||
values[k] = None
|
|
||||||
|
|
||||||
return values
|
return values
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user