From 8c8eb3c679bab6299928d4913ec1319bb5fdc25b Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 16 Jun 2026 12:22:07 +0100 Subject: [PATCH] fix: ci fixes --- application/storage/db/repositories/teams.py | 14 +++++++++++--- .../db/repositories/test_team_resource_sharing.py | 2 -- tests/storage/db/repositories/test_teams.py | 5 ++++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/application/storage/db/repositories/teams.py b/application/storage/db/repositories/teams.py index 136d9bcc..704e3a0e 100644 --- a/application/storage/db/repositories/teams.py +++ b/application/storage/db/repositories/teams.py @@ -116,14 +116,22 @@ class TeamsRepository: ) return row_to_dict(result.fetchone()) + # Each updatable column maps to a CONSTANT SQL fragment. The SET clause is + # assembled only from these literals (selected by whitelisted keys), so no + # user-controlled string ever reaches the query text — values travel as + # bound parameters. Keeps the query injection-free by construction. + _UPDATABLE_COLUMNS = { + "name": "name = :name", + "description": "description = :description", + } + def update(self, team_id: str, fields: dict) -> bool: """Update mutable team fields (``name``, ``description``). updated_at is bumped by the ``teams_set_updated_at`` trigger.""" - allowed = {"name", "description"} - values = {k: v for k, v in fields.items() if k in allowed} + values = {k: v for k, v in fields.items() if k in self._UPDATABLE_COLUMNS} if not values: return False - set_clause = ", ".join(f"{k} = :{k}" for k in values) + set_clause = ", ".join(self._UPDATABLE_COLUMNS[k] for k in values) params = dict(values) params["id"] = team_id result = self._conn.execute( diff --git a/tests/storage/db/repositories/test_team_resource_sharing.py b/tests/storage/db/repositories/test_team_resource_sharing.py index c2cf219a..a25ce546 100644 --- a/tests/storage/db/repositories/test_team_resource_sharing.py +++ b/tests/storage/db/repositories/test_team_resource_sharing.py @@ -2,8 +2,6 @@ from __future__ import annotations -import uuid - from application.storage.db.repositories.prompts import PromptsRepository from application.storage.db.repositories.sources import SourcesRepository from application.storage.db.repositories.user_tools import UserToolsRepository diff --git a/tests/storage/db/repositories/test_teams.py b/tests/storage/db/repositories/test_teams.py index 4cb13e2c..1ccf1743 100644 --- a/tests/storage/db/repositories/test_teams.py +++ b/tests/storage/db/repositories/test_teams.py @@ -67,7 +67,10 @@ class TestTeamsRepository: members = TeamMembersRepository(pg_conn) team = _new_team(pg_conn) members.add_member(team["id"], "alice", role="team_admin") - assert teams.delete(team["id"]) is True + # Keep the side-effecting call off the assert line so it always runs, + # even under `python -O` (asserts stripped). + deleted = teams.delete(team["id"]) + assert deleted is True assert members.list_members(team["id"]) == []