diff --git a/websiteFunctions/dockerviews.py b/websiteFunctions/dockerviews.py index c1d3182de..2d4c6136c 100644 --- a/websiteFunctions/dockerviews.py +++ b/websiteFunctions/dockerviews.py @@ -162,58 +162,6 @@ def restartContainer(request): container.restart() return HttpResponse(json.dumps({'status': 1})) - return HttpResponse('Not allowed') - except Exception as e: - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': str(e) - })) - -@csrf_exempt -@require_login -def executeCommand(request): - try: - if request.method == 'POST': - userID = request.session['userID'] - currentACL = ACLManager.loadedACL(userID) - admin = Administrator.objects.get(pk=userID) - - data = json.loads(request.body) - container_id = data.get('container_id') - command = data.get('command') - site_name = data.get('name') - - # Verify Docker site ownership - try: - docker_site = DockerSites.objects.get(SiteName=site_name) - if currentACL['admin'] != 1 and docker_site.admin != admin and docker_site.admin.owner != admin.pk: - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': 'Not authorized to access this container' - })) - except DockerSites.DoesNotExist: - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': 'Docker site not found' - })) - - docker_manager = DockerManager() - container = docker_manager.get_container(container_id) - - if not container: - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': 'Container not found' - })) - - # Execute the command - result = container.exec_run(command) - - return HttpResponse(json.dumps({ - 'status': 1, - 'output': result.output.decode('utf-8') - })) - return HttpResponse('Not allowed') except Exception as e: return HttpResponse(json.dumps({ diff --git a/websiteFunctions/static/websiteFunctions/DockerContainers.js b/websiteFunctions/static/websiteFunctions/DockerContainers.js index d17da0435..4614497eb 100644 --- a/websiteFunctions/static/websiteFunctions/DockerContainers.js +++ b/websiteFunctions/static/websiteFunctions/DockerContainers.js @@ -347,99 +347,4 @@ app.controller('ListDockersitecontainer', function ($scope, $http) { // Add location service to the controller for the n8n URL $scope.location = window.location; - - // Initialize n8n version info for containers - $scope.initializeN8nVersion = function(container) { - if (!container || !container.id) return; - - $http({ - method: 'POST', - url: '/docker/fetchN8nVersions', - data: { - container_id: container.id - } - }).then(function(response) { - if (response.data.status === 1) { - container.n8nVersion = { - current: response.data.current_version, - latest: response.data.latest_version, - updateAvailable: response.data.update_available - }; - } else { - console.error('Error fetching n8n versions:', response.data.error_message); - } - }, function(error) { - console.error('Error fetching n8n versions:', error); - }); - }; - - // Update n8n function - $scope.updateN8n = function(container) { - if (!container || container.updatingN8n) return; - - container.updatingN8n = true; - - // First stop the container - $http({ - method: 'POST', - url: '/docker/stopContainer', - data: { - container_id: container.id, - name: container.name - } - }).then(function(response) { - if (response.data.status === 1) { - // Execute update command - return $http({ - method: 'POST', - url: '/docker/executeCommand', - data: { - container_id: container.id, - command: 'npm install -g n8n@latest' - } - }); - } else { - throw new Error('Failed to stop container'); - } - }).then(function(response) { - if (response.data.status === 1) { - // Start the container back - return $http({ - method: 'POST', - url: '/docker/startContainer', - data: { - container_id: container.id, - name: container.name - } - }); - } else { - throw new Error('Failed to update n8n'); - } - }).then(function(response) { - if (response.data.status === 1) { - // Refresh version info - $scope.initializeN8nVersion(container); - } else { - throw new Error('Failed to start container'); - } - }).catch(function(error) { - console.error('Error updating n8n:', error); - }).finally(function() { - container.updatingN8n = false; - }); - }; - - // Hook into existing container loading - var originalLunchcontainer = $scope.Lunchcontainer; - if (originalLunchcontainer) { - $scope.Lunchcontainer = function(containerId) { - var result = originalLunchcontainer(containerId); - // Initialize version info after container is loaded - if ($scope.web && $scope.web.environment && - $scope.web.environment.some(function(env) { return env.includes('n8n'); })) { - $scope.initializeN8nVersion($scope.web); - } - return result; - }; - } }); \ No newline at end of file diff --git a/websiteFunctions/templates/websiteFunctions/DockerSiteHome.html b/websiteFunctions/templates/websiteFunctions/DockerSiteHome.html index 4804b25c8..04236e907 100644 --- a/websiteFunctions/templates/websiteFunctions/DockerSiteHome.html +++ b/websiteFunctions/templates/websiteFunctions/DockerSiteHome.html @@ -889,6 +889,49 @@ i.fa:not(.btn i.fa) { margin-right: 10px; } + + /* Version badge styling */ + .version-badge { + display: inline-flex; + align-items: center; + background: #f8f9fa; + border: 1px solid #e9ecef; + border-radius: 4px; + padding: 2px 8px; + margin: 0 8px; + font-size: 12px; + color: #495057; + } + + .version-badge i { + margin-right: 4px; + color: #6c757d; + } + + .update-available { + display: inline-flex; + align-items: center; + background: #fff3cd; + color: #856404; + border-radius: 4px; + padding: 2px 8px; + margin-left: 8px; + font-size: 12px; + border: 1px solid #ffeeba; + } + + .update-available i { + margin-right: 4px; + color: #856404; + } + + /* Ensure proper spacing in container header */ + .container-header h3 { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 8px; + } @@ -1155,12 +1165,12 @@

n8n Container: {$ web.name $} -
- Version {$ web.n8nVersion.current || '...' $} - - Update available: {$ web.n8nVersion.latest $} + + v{$ web.version $} + + Update Available -
+ {$ web.status $} @@ -1179,14 +1189,12 @@ + Open n8n - diff --git a/websiteFunctions/urls.py b/websiteFunctions/urls.py index bc684d3be..263492a83 100755 --- a/websiteFunctions/urls.py +++ b/websiteFunctions/urls.py @@ -183,8 +183,6 @@ urlpatterns = [ path('docker/startContainer', views.startContainer, name='startContainer'), path('docker/stopContainer', views.stopContainer, name='stopContainer'), path('docker/restartContainer', views.restartContainer, name='restartContainer'), - path('docker/executeCommand', views.executeCommand, name='executeCommand'), - path('docker/fetchN8nVersions', views.fetchN8nVersions, name='fetchN8nVersions'), # SSH Configs path('getSSHConfigs', views.getSSHConfigs, name='getSSHConfigs'), @@ -202,5 +200,4 @@ urlpatterns = [ # Catch all for domains path('/', views.launchChild, name='launchChild'), path('', views.domain, name='domain'), - path('fetchN8nVersions', views.fetchN8nVersions, name='fetchN8nVersions'), ] diff --git a/websiteFunctions/views.py b/websiteFunctions/views.py index fcae1f3c7..ddfe3276e 100755 --- a/websiteFunctions/views.py +++ b/websiteFunctions/views.py @@ -17,8 +17,6 @@ from django.views.decorators.csrf import csrf_exempt from .dockerviews import startContainer as docker_startContainer from .dockerviews import stopContainer as docker_stopContainer from .dockerviews import restartContainer as docker_restartContainer -from .dockerviews import DockerManager -from .dockerviews import executeCommand as docker_executeCommand def loadWebsitesHome(request): val = request.session['userID'] @@ -1883,53 +1881,5 @@ def restartContainer(request): if request.method == 'POST': return docker_restartContainer(request) return HttpResponse('Not allowed') - except KeyError: - return redirect(loadLoginPage) - -@csrf_exempt -def fetchN8nVersions(request): - try: - userID = request.session['userID'] - data = json.loads(request.body) - container_id = data.get('container_id') - - docker_manager = DockerManager() - container = docker_manager.get_container(container_id) - - if not container: - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': 'Container not found' - })) - - # Execute command in container to get current n8n version - current_version_cmd = container.exec_run("npm list n8n --json") - current_version_output = current_version_cmd.output.decode('utf-8') - current_version_data = json.loads(current_version_output) - current_version = current_version_data.get('dependencies', {}).get('n8n', {}).get('version', 'unknown') - - # Get latest version from npm - latest_version_cmd = container.exec_run("npm show n8n version") - latest_version = latest_version_cmd.output.decode('utf-8').strip() - - return HttpResponse(json.dumps({ - 'status': 1, - 'current_version': current_version, - 'latest_version': latest_version, - 'update_available': current_version != latest_version - })) - - except Exception as e: - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': str(e) - })) - -@csrf_exempt -def executeCommand(request): - try: - if request.method == 'POST': - return docker_executeCommand(request) - return HttpResponse('Not allowed') except KeyError: return redirect(loadLoginPage) \ No newline at end of file