From 431b787a92f47e405f5487206f9f3412f361683f Mon Sep 17 00:00:00 2001 From: Aday Bujeda Date: Wed, 4 Dec 2024 19:17:21 +0000 Subject: [PATCH] Added support to render widgets partial without any layout furniture --- .../app/controllers/widgets_controller.rb | 31 +++++++++++++ apps/dashboard/config/routes.rb | 2 + .../controllers/widgets_controller_test.rb | 45 +++++++++++++++++++ .../widgets/_widgets_partial_test.html.erb | 1 + .../test/integration/widgets_partial_test.rb | 18 ++++++++ 5 files changed, 97 insertions(+) create mode 100644 apps/dashboard/app/controllers/widgets_controller.rb create mode 100644 apps/dashboard/test/controllers/widgets_controller_test.rb create mode 100644 apps/dashboard/test/fixtures/config/views/widgets/_widgets_partial_test.html.erb create mode 100644 apps/dashboard/test/integration/widgets_partial_test.rb diff --git a/apps/dashboard/app/controllers/widgets_controller.rb b/apps/dashboard/app/controllers/widgets_controller.rb new file mode 100644 index 0000000000..cdd2b724d7 --- /dev/null +++ b/apps/dashboard/app/controllers/widgets_controller.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +# The Controller to render widget templates without any layout furniture +class WidgetsController < ApplicationController + + def show + widget_path = File.join('/widgets', params[:widget_path]) + + unless valid_path?(widget_path) + render plain: "400 Bad Request. Invalid widget path: #{widget_path}", status: :bad_request + return + end + + + widget_exists = lookup_context.exists?(widget_path, [], true) + unless widget_exists + render plain: "404 Widget not found: #{widget_path}", status: :not_found + return + end + + render partial: widget_path, layout: false + end + + private + + # Checks if the widget path contains only allowed characters + def valid_path?(widget_path) + widget_path.match?(/\A[a-zA-Z0-9_\-\/]+\z/) + end +end + diff --git a/apps/dashboard/config/routes.rb b/apps/dashboard/config/routes.rb index 54c639252c..bf13ea0073 100644 --- a/apps/dashboard/config/routes.rb +++ b/apps/dashboard/config/routes.rb @@ -106,6 +106,8 @@ post 'settings', :to => 'settings#update' + match '/widgets/*widget_path', to: 'widgets#show', via: [:get, :post], as: 'widgets' + # Support ticket routes if Configuration.support_ticket_enabled? get '/support', to: 'support_ticket#new' diff --git a/apps/dashboard/test/controllers/widgets_controller_test.rb b/apps/dashboard/test/controllers/widgets_controller_test.rb new file mode 100644 index 0000000000..251f7dd490 --- /dev/null +++ b/apps/dashboard/test/controllers/widgets_controller_test.rb @@ -0,0 +1,45 @@ +require "test_helper" + +class WidgetsControllerTest < ActiveSupport::TestCase + + def setup + @controller = WidgetsController.new + end + + test 'valid_path? validates widget paths' do + refute @controller.send(:valid_path?, '/test!') + refute @controller.send(:valid_path?, '/test/../../outside_dir') + refute @controller.send(:valid_path?, '@user:pwd/dir') + + assert @controller.send(:valid_path?, 'test') + assert @controller.send(:valid_path?, '/test') + assert @controller.send(:valid_path?, '/test/path/widget') + assert @controller.send(:valid_path?, '/test_path/widget') + assert @controller.send(:valid_path?, '/test-path/widget_under/name') + end + + test 'show should return HTTP 400 when invalid widget path is used' do + @params = ActionController::Parameters.new({ widget_path: '!!invalid' }) + @controller.stubs(:params).returns(@params) + @controller.expects(:render).with(plain: '400 Bad Request. Invalid widget path: /widgets/!!invalid', status: :bad_request) + + @controller.show + end + + test 'show should return HTTP 404 when valid widget path is not found in the system' do + @params = ActionController::Parameters.new({ widget_path: '/valid/path' }) + @controller.stubs(:params).returns(@params) + @controller.expects(:render).with(plain: '404 Widget not found: /widgets/valid/path', status: :not_found) + + @controller.show + end + + test 'show should render widget when valid widget path is found in the system' do + @params = ActionController::Parameters.new({ widget_path: '/valid/path' }) + @controller.stubs(:params).returns(@params) + @controller.lookup_context.stubs(:exists?).returns(true) + @controller.expects(:render).with(partial: '/widgets/valid/path', layout: false) + + @controller.show + end +end diff --git a/apps/dashboard/test/fixtures/config/views/widgets/_widgets_partial_test.html.erb b/apps/dashboard/test/fixtures/config/views/widgets/_widgets_partial_test.html.erb new file mode 100644 index 0000000000..ccdc29dc66 --- /dev/null +++ b/apps/dashboard/test/fixtures/config/views/widgets/_widgets_partial_test.html.erb @@ -0,0 +1 @@ +

test response from widget partial

\ No newline at end of file diff --git a/apps/dashboard/test/integration/widgets_partial_test.rb b/apps/dashboard/test/integration/widgets_partial_test.rb new file mode 100644 index 0000000000..9349dba286 --- /dev/null +++ b/apps/dashboard/test/integration/widgets_partial_test.rb @@ -0,0 +1,18 @@ +require 'html_helper' +require 'test_helper' + +class WidgetsPartialTest < ActionDispatch::IntegrationTest + + test 'should render widget partial without any layout furniture' do + get widgets_url('widgets_partial_test') + + assert_response :ok + assert_equal '

test response from widget partial

', @response.body + end + + test 'should render return 404 response when widget is missing' do + get widgets_url('missing_widget') + + assert_response :not_found + end +end