-
Notifications
You must be signed in to change notification settings - Fork 0
Migrate from Qdrant to Postgres #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
939ea74
4e49dd1
22c4b44
ee0f184
d63d894
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,101 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"""JSON indexing API routes""" | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import json | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import logging | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import tempfile | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import os | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from aiohttp import web | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from data_loading.db_load import loadJsonToDB | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
logger = logging.getLogger(__name__) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def setup_indexing_routes(app: web.Application): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"""Setup indexing API routes""" | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
app.router.add_post('/api/index/json', index_json_handler) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
async def index_json_handler(request: web.Request) -> web.Response: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
""" | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Handle direct JSON data indexing. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Expects JSON body with: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
- data (array or object): JSON data to index (single object or array of objects) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
- site (str): Site identifier (e.g., "user_qdrant", "company_qdrant", etc.) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
- batch_size (int, optional): Batch size for processing (default: 100) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
- delete_existing (bool, optional): Whether to delete existing entries for this site (default: false) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
- database (str, optional): Specific database endpoint to use | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
""" | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
try: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
body = await request.json() | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
data = body.get('data') | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
site = body.get('site') | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if not data or not site: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return web.json_response({ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"success": False, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"error": "Missing required parameters: data and site" | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, status=400) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
batch_size = body.get('batch_size', 100) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
delete_existing = body.get('delete_existing', False) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
database = body.get('database') | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Create temporary JSONL file from the data | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
temp_path = None | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
try: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.jsonl', delete=False, encoding='utf-8') as temp_file: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if isinstance(data, list): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Array of objects | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for item in data: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
temp_file.write(json.dumps(item) + '\n') | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
else: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Single object | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
temp_file.write(json.dumps(data) + '\n') | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
temp_path = temp_file.name | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
logger.info(f"Starting JSON indexing: site={site}, objects={len(data) if isinstance(data, list) else 1}") | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Use loadJsonToDB with the temporary file | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
total_documents = await loadJsonToDB( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
file_path=temp_path, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
site=site, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
batch_size=batch_size, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
delete_existing=delete_existing, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
force_recompute=False, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
database=database | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
logger.info(f"JSON indexing completed: {total_documents} documents indexed for site {site}") | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -32,6 +32,8 @@ | ||
|
||
data = body.get('data') | ||
site = body.get('site') | ||
# Sanitize site input to prevent log injection | ||
safe_site = site.replace('\r', '').replace('\n', '') if site else '' | ||
|
||
if not data or not site: | ||
return web.json_response({ | ||
@@ -57,7 +59,7 @@ | ||
|
||
temp_path = temp_file.name | ||
|
||
logger.info(f"Starting JSON indexing: site={site}, objects={len(data) if isinstance(data, list) else 1}") | ||
logger.info(f"Starting JSON indexing: site={safe_site}, objects={len(data) if isinstance(data, list) else 1}") | ||
|
||
# Use loadJsonToDB with the temporary file | ||
total_documents = await loadJsonToDB( | ||
@@ -69,7 +71,7 @@ | ||
database=database | ||
) | ||
|
||
logger.info(f"JSON indexing completed: {total_documents} documents indexed for site {site}") | ||
logger.info(f"JSON indexing completed: {total_documents} documents indexed for site {safe_site}") | ||
|
||
# Return success=False if no documents were indexed | ||
success = total_documents > 0 |
Check failure
Code scanning / CodeQL
Log Injection High
Copilot Autofix
AI about 2 months ago
To fix this log injection vulnerability, sanitize the
site
user-supplied value before logging it. The generally recommended approach for plain-text logs is to strip newlines and carriage returns (\r
,\n
,\r\n
) from the value to prevent attackers from injecting extra log lines. This can be achieved by calling.replace()
on the variable before interpolation in the log message.Best practice is to sanitize as close as possible to usage, but for readability and to prevent accidental omission, it makes sense to sanitize just above where the variable is first used in a log statement. In this file, sanitize
site
just before it's logged:site
usingsite.replace('\r', '').replace('\n', '')
and use the sanitized variable in the log message.site_for_log
.Make this change where
site
is logged on line 60 (and optionally line 72), by introducing a sanitized version just before.