Add functionality to query DB through settings

This commit is contained in:
Peter Stockings
2025-12-01 10:04:19 +11:00
parent 0f26545c51
commit 290b141d32
2 changed files with 253 additions and 3 deletions

View File

@@ -205,3 +205,83 @@ def get_database_schema():
})
return schema_data
@settings.route("/execute_query", methods=["POST"])
@login_required
def execute_query():
"""Execute a user-scoped SQL query"""
query = request.json.get('query', '').strip()
if not query:
return {"error": "No query provided"}, 400
# Basic validation - must be SELECT only
query_upper = query.upper()
if not query_upper.startswith('SELECT'):
return {"error": "Only SELECT queries are allowed"}, 400
# Check for dangerous keywords
dangerous_keywords = ['DROP', 'DELETE', 'INSERT', 'UPDATE', 'ALTER', 'CREATE', 'TRUNCATE', 'GRANT', 'REVOKE']
for keyword in dangerous_keywords:
if keyword in query_upper:
return {"error": f"Keyword '{keyword}' is not allowed"}, 400
user_id = current_user.id
# List of tables that have user_id column
user_scoped_tables = [
'http_functions', 'timer_functions', 'shared_environments',
'api_keys', 'http_function_invocations', 'timer_function_invocations'
]
# Automatically add user_id filter if querying user-scoped tables
modified_query = query
for table in user_scoped_tables:
if table in query.lower():
# Add WHERE clause if not present
if 'WHERE' not in query_upper:
modified_query = f"{query} WHERE {table}.user_id = {user_id}"
# Append to existing WHERE clause
elif f'{table}.user_id' not in query.lower() and 'user_id' not in query.lower():
modified_query = f"{query} AND {table}.user_id = {user_id}"
break
# Limit results to prevent massive queries
if 'LIMIT' not in query_upper:
modified_query = f"{modified_query} LIMIT 100"
try:
results = db.execute(modified_query)
if not results:
return {
"columns": [],
"rows": [],
"row_count": 0,
"message": "Query executed successfully, but returned no results."
}
# Convert results to JSON-serializable format
columns = list(results[0].keys()) if results else []
rows = []
for row in results:
row_data = []
for col in columns:
value = row[col]
# Convert datetime to string
if hasattr(value, 'isoformat'):
value = value.isoformat()
row_data.append(value)
rows.append(row_data)
return {
"columns": columns,
"rows": rows,
"row_count": len(rows),
"message": f"Query executed successfully. {len(rows)} row(s) returned.",
"query_executed": modified_query
}
except Exception as e:
return {"error": f"Query execution failed: {str(e)}"}, 500