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 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-04-11 19:09:11 -04:00
parent 0ecc5a97d5
commit dfb5289188
2 changed files with 10 additions and 2 deletions

View File

@@ -487,9 +487,13 @@ async def post_obj(
# Enforce account ownership AFTER sanitize_payload so the integer account_id goes straight # 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. # 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 not account.super and account.auth_method != 'bypass' and account.account_id:
if 'account_id' in input_model.__fields__: 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): if sql_insert_result := sql_insert(data=data_to_insert, table_name=table_name_insert):
new_obj_id = sql_insert_result new_obj_id = sql_insert_result

View File

@@ -332,9 +332,13 @@ async def post_child_obj(
# Enforce account ownership AFTER sanitize_payload so the integer account_id goes # 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. # 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 not account.super and account.auth_method != 'bypass' and account.account_id:
if 'account_id' in input_model.__fields__: 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 # 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. # set — ensuring the child is always linked to the correct parent.