diff --git a/backend/app/database/albums.py b/backend/app/database/albums.py index b9e5b149a..2db8df4e5 100644 --- a/backend/app/database/albums.py +++ b/backend/app/database/albums.py @@ -169,23 +169,43 @@ def db_get_album_images(album_id: str): def db_add_images_to_album(album_id: str, image_ids: list[str]): + """ + Safely adds images to an album using parameterized queries. + Maintains UUID support and uses efficient single queries. + """ + # Validate input type + if not isinstance(image_ids, list): + raise ValueError("image_ids must be a list of IDs") + + # Remove integer conversion - keep IDs as strings for UUID support + sanitized_ids = [] + for img_id in image_ids: + # Basic validation - ensure it's a non-empty string + if isinstance(img_id, str) and img_id.strip(): + sanitized_ids.append(img_id.strip()) + + if not sanitized_ids: + raise ValueError("No valid image IDs provided") + with get_db_connection() as conn: cursor = conn.cursor() - query = ( - f"SELECT id FROM images WHERE id IN ({','.join('?' for _ in image_ids)})" - ) - cursor.execute(query, image_ids) + # Generate placeholders safely based on list length + placeholders = ",".join(["?"] * len(sanitized_ids)) + query = f"SELECT id FROM images WHERE id IN ({placeholders})" + cursor.execute(query, sanitized_ids) # Pass string IDs directly valid_images = [row[0] for row in cursor.fetchall()] - if valid_images: - cursor.executemany( - "INSERT OR IGNORE INTO album_images (album_id, image_id) VALUES (?, ?)", - [(album_id, img_id) for img_id in valid_images], - ) - else: + if not valid_images: raise ValueError("None of the provided image IDs exist in the database.") + # Insert into album_images using executemany + cursor.executemany( + "INSERT OR IGNORE INTO album_images (album_id, image_id) VALUES (?, ?)", + [(album_id, img_id) for img_id in valid_images], + ) + conn.commit() + def db_remove_image_from_album(album_id: str, image_id: str): with get_db_connection() as conn: