diff --git a/websiteFunctions/dockerviews.py b/websiteFunctions/dockerviews.py index 1d7777c61..c428c21ea 100644 --- a/websiteFunctions/dockerviews.py +++ b/websiteFunctions/dockerviews.py @@ -194,68 +194,99 @@ def n8n_container_operation(request): 'error_message': 'Container not found' })) + # Determine the port where n8n is running + container_info = container.attrs + port_bindings = container_info.get('HostConfig', {}).get('PortBindings', {}) + n8n_port = None + + for container_port, host_ports in port_bindings.items(): + if container_port.startswith('5678'): + n8n_port = host_ports[0]['HostPort'] + break + + if not n8n_port: + return HttpResponse(json.dumps({ + 'status': 0, + 'error_message': 'Could not determine n8n port' + })) + + # Extract the n8n API key from environment variables + n8n_api_key = None + environment_vars = container_info.get('Config', {}).get('Env', []) + + for env_var in environment_vars: + if env_var.startswith('N8N_API_KEY='): + n8n_api_key = env_var.split('=', 1)[1] + break + + # If API key not found in environment variables, check if it's set to a default value + if not n8n_api_key: + n8n_api_key = 'n8n_api_123abc456def789' # A common default, can be customized + logging.writeToFile(f"No N8N_API_KEY found in container environment, using default") + + # Set up n8n API URL and headers + host_ip = request.get_host().split(':')[0] + n8n_base_url = f"http://{host_ip}:{n8n_port}/api/v1" + + headers = { + 'X-N8N-API-KEY': n8n_api_key, + 'Accept': 'application/json', + 'Content-Type': 'application/json' + } + # Handle different operations if operation == 'create_backup': try: - # Determine the port where n8n is running - container_info = container.attrs - port_bindings = container_info.get('HostConfig', {}).get('PortBindings', {}) - n8n_port = None - - for container_port, host_ports in port_bindings.items(): - if container_port.startswith('5678'): - n8n_port = host_ports[0]['HostPort'] - break - - if not n8n_port: - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': 'Could not determine n8n port' - })) - # Get backup options from request backup_options = data.get('options', {}) include_credentials = backup_options.get('includeCredentials', True) include_executions = backup_options.get('includeExecutions', False) - # Set up n8n API URL - host_ip = request.get_host().split(':')[0] - n8n_base_url = f"http://{host_ip}:{n8n_port}/api/v1" - # Initialize the backup data dictionary backup_data = {} - # Fetch workflows - # Get n8n workflows (no authentication required for basic n8n) - workflows_response = requests.get(f"{n8n_base_url}/workflows") + # Fetch workflows with API key authentication + workflows_response = requests.get( + f"{n8n_base_url}/workflows", + headers=headers + ) if workflows_response.status_code == 200: backup_data['workflows'] = workflows_response.json() else: - logging.writeToFile(f"Failed to fetch n8n workflows: {workflows_response.status_code} - {workflows_response.text}") + error_message = workflows_response.text + logging.writeToFile(f"Failed to fetch n8n workflows: {workflows_response.status_code} - {error_message}") return HttpResponse(json.dumps({ 'status': 0, - 'error_message': f'Failed to fetch workflows: {workflows_response.text}' + 'error_message': f'Failed to fetch workflows: {error_message}' })) # Get credentials if requested if include_credentials: - credentials_response = requests.get(f"{n8n_base_url}/credentials") + credentials_response = requests.get( + f"{n8n_base_url}/credentials", + headers=headers + ) if credentials_response.status_code == 200: backup_data['credentials'] = credentials_response.json() else: - logging.writeToFile(f"Failed to fetch n8n credentials: {credentials_response.status_code} - {credentials_response.text}") + error_message = credentials_response.text + logging.writeToFile(f"Failed to fetch n8n credentials: {credentials_response.status_code} - {error_message}") # Don't fail the whole backup just because credentials failed # Get execution data if requested if include_executions: - executions_response = requests.get(f"{n8n_base_url}/executions") + executions_response = requests.get( + f"{n8n_base_url}/executions", + headers=headers + ) if executions_response.status_code == 200: backup_data['executions'] = executions_response.json() else: - logging.writeToFile(f"Failed to fetch n8n executions: {executions_response.status_code} - {executions_response.text}") + error_message = executions_response.text + logging.writeToFile(f"Failed to fetch n8n executions: {executions_response.status_code} - {error_message}") # Don't fail the whole backup just because executions failed # Include metadata @@ -284,22 +315,6 @@ def n8n_container_operation(request): elif operation == 'restore_backup': try: - # Determine the port where n8n is running - container_info = container.attrs - port_bindings = container_info.get('HostConfig', {}).get('PortBindings', {}) - n8n_port = None - - for container_port, host_ports in port_bindings.items(): - if container_port.startswith('5678'): - n8n_port = host_ports[0]['HostPort'] - break - - if not n8n_port: - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': 'Could not determine n8n port' - })) - # Get backup data from request backup_data = data.get('backup_data') @@ -309,20 +324,20 @@ def n8n_container_operation(request): 'error_message': 'No backup data provided' })) - # Set up n8n API URL - host_ip = request.get_host().split(':')[0] - n8n_base_url = f"http://{host_ip}:{n8n_port}/api/v1" - # Restore workflows if 'workflows' in backup_data: # First, get the list of existing workflows to avoid duplicates - existing_workflows_response = requests.get(f"{n8n_base_url}/workflows") + existing_workflows_response = requests.get( + f"{n8n_base_url}/workflows", + headers=headers + ) if existing_workflows_response.status_code != 200: - logging.writeToFile(f"Failed to fetch existing workflows: {existing_workflows_response.status_code} - {existing_workflows_response.text}") + error_message = existing_workflows_response.text + logging.writeToFile(f"Failed to fetch existing workflows: {existing_workflows_response.status_code} - {error_message}") return HttpResponse(json.dumps({ 'status': 0, - 'error_message': f'Failed to fetch existing workflows: {existing_workflows_response.text}' + 'error_message': f'Failed to fetch existing workflows: {error_message}' })) existing_workflows = existing_workflows_response.json() @@ -339,25 +354,32 @@ def n8n_container_operation(request): # Update existing workflow update_response = requests.put( f"{n8n_base_url}/workflows/{existing_workflow_names[workflow['name']]}", + headers=headers, json=workflow ) if update_response.status_code not in [200, 201]: - logging.writeToFile(f"Failed to update workflow: {update_response.status_code} - {update_response.text}") + error_message = update_response.text + logging.writeToFile(f"Failed to update workflow: {update_response.status_code} - {error_message}") else: # Create new workflow create_response = requests.post( f"{n8n_base_url}/workflows", + headers=headers, json=workflow ) if create_response.status_code not in [200, 201]: - logging.writeToFile(f"Failed to create workflow: {create_response.status_code} - {create_response.text}") + error_message = create_response.text + logging.writeToFile(f"Failed to create workflow: {create_response.status_code} - {error_message}") # Restore credentials if included in backup if 'credentials' in backup_data: # First, get existing credentials to avoid duplicates - existing_creds_response = requests.get(f"{n8n_base_url}/credentials") + existing_creds_response = requests.get( + f"{n8n_base_url}/credentials", + headers=headers + ) if existing_creds_response.status_code == 200: existing_creds = existing_creds_response.json() @@ -374,22 +396,27 @@ def n8n_container_operation(request): # Update existing credential update_response = requests.put( f"{n8n_base_url}/credentials/{existing_cred_names[credential['name']]}", + headers=headers, json=credential ) if update_response.status_code not in [200, 201]: - logging.writeToFile(f"Failed to update credential: {update_response.status_code} - {update_response.text}") + error_message = update_response.text + logging.writeToFile(f"Failed to update credential: {update_response.status_code} - {error_message}") else: # Create new credential create_response = requests.post( f"{n8n_base_url}/credentials", + headers=headers, json=credential ) if create_response.status_code not in [200, 201]: - logging.writeToFile(f"Failed to create credential: {create_response.status_code} - {create_response.text}") + error_message = create_response.text + logging.writeToFile(f"Failed to create credential: {create_response.status_code} - {error_message}") else: - logging.writeToFile(f"Failed to fetch existing credentials: {existing_creds_response.status_code} - {existing_creds_response.text}") + error_message = existing_creds_response.text + logging.writeToFile(f"Failed to fetch existing credentials: {existing_creds_response.status_code} - {error_message}") return HttpResponse(json.dumps({ 'status': 1, @@ -411,6 +438,7 @@ def n8n_container_operation(request): return HttpResponse('Not allowed') except Exception as e: + logging.writeToFile(f"Error in n8n_container_operation: {str(e)}") return HttpResponse(json.dumps({ 'status': 0, 'error_message': str(e)