From dfb52891885b54efa5b497c91b008b2e3582c759 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Sat, 11 Apr 2026 19:09:11 -0400 Subject: [PATCH] fix: skip account_id injection when model excludes it from DB writes After the sanitize_payload order fix, account_id was being re-injected into data_to_insert for models that explicitly list account_id in fields_to_exclude_from_db (e.g. event_badge, event_device). Those tables have no account_id column, causing INSERT failures. Guard the post-sanitize account_id injection in both api_crud_v3.py and api_crud_v3_nested.py by checking fields_to_exclude_from_db first. Co-Authored-By: Claude Sonnet 4.6 --- app/routers/api_crud_v3.py | 6 +++++- app/routers/api_crud_v3_nested.py | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/routers/api_crud_v3.py b/app/routers/api_crud_v3.py index c7c5a0d..c39824c 100644 --- a/app/routers/api_crud_v3.py +++ b/app/routers/api_crud_v3.py @@ -487,9 +487,13 @@ async def post_obj( # Enforce account ownership AFTER sanitize_payload so the integer account_id goes straight # to the DB without conflicting with Vision ID string constraints in the model. + # Guard: skip if the model explicitly excludes account_id from DB writes (e.g. event_badge, + # event_device — the column does not exist in those tables). if not account.super and account.auth_method != 'bypass' and account.account_id: if 'account_id' in input_model.__fields__: - data_to_insert['account_id'] = account.account_id + excluded = getattr(input_model, 'fields_to_exclude_from_db', []) + if 'account_id' not in excluded: + data_to_insert['account_id'] = account.account_id if sql_insert_result := sql_insert(data=data_to_insert, table_name=table_name_insert): new_obj_id = sql_insert_result diff --git a/app/routers/api_crud_v3_nested.py b/app/routers/api_crud_v3_nested.py index 7386305..82c2e2b 100644 --- a/app/routers/api_crud_v3_nested.py +++ b/app/routers/api_crud_v3_nested.py @@ -332,9 +332,13 @@ async def post_child_obj( # Enforce account ownership AFTER sanitize_payload so the integer account_id goes # straight to the DB without conflicting with Vision ID string constraints in the model. + # Guard: skip if the model explicitly excludes account_id from DB writes (e.g. event_badge, + # event_device — the column does not exist in those tables). if not account.super and account.auth_method != 'bypass' and account.account_id: if 'account_id' in input_model.__fields__: - data_to_insert['account_id'] = account.account_id + excluded = getattr(input_model, 'fields_to_exclude_from_db', []) + if 'account_id' not in excluded: + data_to_insert['account_id'] = account.account_id # Re-inject parent FK last — overrides anything sanitize_payload or the model may have # set — ensuring the child is always linked to the correct parent.