fix(v3-actions): implement from_hosted_file and harden vision IDs

1. Implemented specialized 'from_hosted_file' action for Event Files.\n2. Fixed ValueError in Pydantic models by removing default/default_factory conflict.\n3. Hardened integer stripping to strictly enforce Vision Standards.\n4. Updated documentation for the new action route.
This commit is contained in:
Scott Idem
2026-02-06 16:23:18 -05:00
parent 64d73c4d5c
commit 8270f7ff7a
6 changed files with 180 additions and 142 deletions

View File

@@ -198,6 +198,84 @@ async def upload_event_file_action(
return mk_resp(data=event_file_results, status_message=f"Successfully processed {len(event_file_results)} event files.")
@router.post('/from_hosted_file/{hosted_file_id}', response_model=Resp_Body_Base)
async def create_event_file_from_hosted_file_action(
event_file_obj: Event_File_Base,
hosted_file_id: str = Path(..., min_length=11, max_length=22),
inc_hosted_file: bool = Query(False),
return_obj: bool = Query(True),
account: AccountContext = Depends(get_account_context),
delay: DelayParams = Depends(),
):
"""
Specialized Action: Create Event File from Existing Hosted File.
This endpoint allows the frontend to associate an ALREADY UPLOADED hosted_file
with an event-specific context (e.g., event_session, exhibit).
Matches V3 Vision ID Standard:
- Accepts string ID in path.
- Resolves relational IDs in body via Event_File_Base root_validator.
"""
if delay.sleep_time_s > 0: await asyncio.sleep(delay.sleep_time_s)
# 1. Verify physical file exists
hf_rec = load_hosted_file_obj(hosted_file_id=hosted_file_id)
if not hf_rec:
raise HTTPException(status_code=404, detail=f"Hosted file '{hosted_file_id}' not found.")
# 2. Prepare event_file data
# The Event_File_Base model now standardizes all IDs to Union[int, str]
# and its root_validator handles the string->int resolution during instantiation.
ef_data = event_file_obj.dict(exclude_unset=True)
ef_data['hosted_file_id'] = hosted_file_id # Inject the path ID
# Re-instantiate to trigger hardened Vision resolution
validated_ef = Event_File_Base(**ef_data)
# 3. Standard Generic Linking (Ensures hosted_file_link exists)
# We need the integers for the method call
hf_id_int = redis_lookup_id_random(record_id_random=hosted_file_id, table_name='hosted_file')
link_to_id_int = redis_lookup_id_random(record_id_random=validated_ef.for_id, table_name=validated_ef.for_type)
create_hosted_file_link(
account_id = account.account_id,
hosted_file_id = hf_id_int,
link_to_type = validated_ef.for_type,
link_to_id = link_to_id_int
)
# 4. Create Event File record
res_ef_id = create_event_file_obj(event_file_obj_new=validated_ef)
if res_ef_id is True:
# Update instead of insert - find the ID
lookup_res = sql_select(
table_name='event_file',
data={
'hosted_file_id': hf_id_int,
'for_type': validated_ef.for_type,
'for_id': link_to_id_int
}
)
if lookup_res: res_ef_id = lookup_res.get('id')
if not isinstance(res_ef_id, int):
raise HTTPException(status_code=400, detail="Failed to create event_file record.")
# 5. Return result
if return_obj:
enriched_ef = load_event_file_obj(event_file_id=res_ef_id, inc_hosted_file=inc_hosted_file, model_as_dict=True)
# Vision Transformer: Ensure clean ID for frontend
if enriched_ef and not isinstance(enriched_ef.get('id'), str):
rid = get_id_random(res_ef_id, table_name='event_file')
enriched_ef['id'] = rid
enriched_ef['event_file_id'] = rid
return mk_resp(data=enriched_ef)
return mk_resp(data={"event_file_id": get_id_random(res_ef_id, 'event_file')})
@router.get('/{event_file_id}/download')
async def download_event_file_action(
response: Response,