Add functionality to query DB through settings
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user