From 4e3b56ecad1f101a2fe8023fb7e2e2f1c72c4dc1 Mon Sep 17 00:00:00 2001 From: Hans-Georg Winkler Date: Wed, 6 Nov 2024 15:38:17 +0100 Subject: [PATCH] fix(assets): assets without hash and error message (#1455) --- app/controllers/application_controller.rb | 32 ++++---- app/controllers/scope_controller.rb | 93 +++++++++++----------- config/initializers/domain_config.rb | 29 ++++--- config/initializers/sprockets_processor.rb | 10 +-- 4 files changed, 84 insertions(+), 80 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index df4ee90acc..8b2eb42036 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,8 +1,8 @@ -require "core/audit_logger" +require 'core/audit_logger' # This class implements functionality to support modal views. # All subclasses which require modal views should inherit from this class. class ApplicationController < ActionController::Base - layout "application" + layout 'application' include ApplicationHelper # includes services method @@ -33,24 +33,24 @@ class ApplicationController < ActionController::Base # has several bugs) # "beta" (if it's almost ready for public release) def release_state - "public_release" + 'public_release' end # catch all api errors and render exception page - rescue_from "Elektron::Errors::Request" do |exception| + rescue_from 'Elektron::Errors::Request' do |exception| options = { - title: "Backend Slowdown Detected", + title: 'Backend Slowdown Detected', description: - "We are currently experiencing a higher latency in our " \ - "backend calls. This should be fixed momentarily. Please " \ - "try again in a couple of minutes.", + 'We are currently experiencing a higher latency in our ' \ + 'backend calls. This should be fixed momentarily. Please ' \ + 'try again in a couple of minutes.', warning: true, - sentry: false, + sentry: false } # send to sentry if exception isn't a timeout error - options[:sentry] = true unless exception.message == "Net::ReadTimeout" + options[:sentry] = true unless exception.message == 'Net::ReadTimeout' render_exception_page(exception, options) end @@ -61,28 +61,28 @@ def modal? end def modal_size - params[:modal_size] || "modal-xl" + params[:modal_size] || 'modal-xl' end def render(*args) options = args.extract_options! - options[:layout] = "modal" if modal? - super *args, options + options[:layout] = 'modal' if modal? + super(*args, options) end def redirect_to(options = {}, response_options = {}) if request.format == Mime[:json] || modal? || params[:polling_service] || - params[:do_not_redirect] + params[:do_not_redirect] head :ok, location: url_for(options) else - # Note: please do not use "allow_other_host: true" here just pass it as an option from the controller where redirect_to is called + # NOTE: please do not use "allow_other_host: true" here just pass it as an option from the controller where redirect_to is called super options, response_options end end def plugin_name if @plugin_name.blank? - tokens = self.class.name.split("::").collect(&:underscore) + tokens = self.class.name.split('::').collect(&:underscore) @plugin_name = tokens.find { |t| Core::PluginsManager.plugin?(t) } end @plugin_name diff --git a/app/controllers/scope_controller.rb b/app/controllers/scope_controller.rb index 9f2dea0be2..1e1d0d3300 100644 --- a/app/controllers/scope_controller.rb +++ b/app/controllers/scope_controller.rb @@ -6,23 +6,24 @@ class ScopeController < ::ApplicationController # keep the before_action with prepend to ensure that the load_scoped_objects method is called first prepend_before_action :load_scoped_objects + prepend_before_action :create_default_domain_config # At this point is the domain configuration already loaded and the scoped domain and project are set. # The plugin_name is set by the ApplicationController which is inherited by this class. before_action :hidden_plugin_redirect # to prevent unauthorized access to hidden plugins we redirect to a 404 page # if the plugin is hidden for the current domain - def hidden_plugin_redirect - if @domain_config.plugin_hidden?(plugin_name.to_s) - redirect_to "/error-404" - end + def hidden_plugin_redirect + return unless @domain_config.plugin_hidden?(plugin_name.to_s) + + redirect_to '/error-404' end def load_scoped_objects # initialize scoped domain's and project's friendly id # use existing, user's or default domain domain_id = - (params[:domain_id] || Rails.application.config.service_user_domain_name) + params[:domain_id] || Rails.application.config.service_user_domain_name project_id = params[:project_id] @scoped_domain_fid = @scoped_domain_id = domain_id @@ -32,9 +33,7 @@ def load_scoped_objects rescoping_service = Dashboard::RescopingService.new(service_user) domain_friendly_id = rescoping_service.domain_friendly_id(@scoped_domain_fid) - unless domain_friendly_id - raise Core::Error::DomainNotFound, "Domain #{domain_id} not found!" - end + raise Core::Error::DomainNotFound, "Domain #{domain_id} not found!" unless domain_friendly_id # set scoped domain parameters @scoped_domain_id = domain_friendly_id.key @@ -46,7 +45,7 @@ def load_scoped_objects project_friendly_id = rescoping_service.project_friendly_id( @scoped_domain_id, - @scoped_project_fid, + @scoped_project_fid ) end @@ -57,40 +56,35 @@ def load_scoped_objects @scoped_project_name = project_friendly_id.name end - #puts "SCOPED CONTROLLER" - #puts @scoped_domain_id - #puts @scoped_project_id + # puts "SCOPED CONTROLLER" + # puts @scoped_domain_id + # puts @scoped_project_id - if domain_id != @scoped_domain_fid || project_id != @scoped_project_fid - # url_for does not work for plugins. Use path instead! - - if @scoped_domain_id - # replace domain_id with domain friendly id + # url_for does not work for plugins. Use path instead! + if (domain_id != @scoped_domain_fid || project_id != @scoped_project_fid) && @scoped_domain_id + # replace domain_id with domain friendly id + new_path = + request.path.gsub( + %r{^/#{domain_id}/(?.*)}, + '/' + @scoped_domain_fid + '/\k' + ) + new_path = "/#{@scoped_domain_fid}#{new_path}" unless new_path.include?(@scoped_domain_fid) + # replace project_id with freindly id if given + if @scoped_project_id new_path = - request.path.gsub( - %r{^\/#{domain_id}\/(?.*)}, - "/" + @scoped_domain_fid + '/\k', + new_path.gsub( + %r{^/(?.+)/#{project_id}/(?.*)}, + '/\k/' + @scoped_project_fid + '/\k' ) - unless new_path.include?(@scoped_domain_fid) - new_path = "/#{@scoped_domain_fid}#{new_path}" - end - # replace project_id with freindly id if given - if @scoped_project_id - new_path = - new_path.gsub( - %r{^\/(?.+)\/#{project_id}\/(?.*)}, - '/\k/' + @scoped_project_fid + '/\k', - ) - end - - url_params = request.query_parameters - url_params.delete(:domain_id) - url_params.delete(:project_id) - new_path += "?#{url_params.to_query}" unless url_params.empty? - - redirect_to new_path unless params[:modal] end + + url_params = request.query_parameters + url_params.delete(:domain_id) + url_params.delete(:project_id) + new_path += "?#{url_params.to_query}" unless url_params.empty? + + redirect_to new_path unless params[:modal] end @policy_default_params = { target: {} } @@ -99,25 +93,32 @@ def load_scoped_objects @can_access_domain = !@scoped_domain_name.nil? @can_access_project = !@scoped_project_name.nil? - - # the presence of this variable is tested in spec/controllers/scope_controller_spec.rb - @domain_config = DomainConfig.new(@scoped_domain_name) + # from here the real domain name is known so we can update the domain config with this name + @domain_config.update_domain(@scoped_domain_name) end rescue_from( - "Core::Error::ServiceUserNotAuthenticated", - "Core::Error::DomainNotFound", + 'Core::Error::ServiceUserNotAuthenticated', + 'Core::Error::DomainNotFound' ) do |exception| render_exception_page( exception, - title: "Unsupported Domain", - description: ->(_e, controller) do + title: 'Unsupported Domain', + description: lambda do |_e, controller| "A domain with the name #{controller.params[:domain_id]} doesn't seem to exist. Please check the spelling and try again" end, details: :message, warning: true, sentry: true, - status: 404, + status: 404 ) end + + # this method creates a default domain config object from the domain_id parameter + # the domain_id parameter can be the name or the id of the domain + # the real name is resolved in the load_scoped_objects method and also updates the domain config + # this method called in the prepend_before_action chain as first to ensure that the domain config is available + def create_default_domain_config + @domain_config = DomainConfig.new(params[:domain_id]) + end end diff --git a/config/initializers/domain_config.rb b/config/initializers/domain_config.rb index 2e1f9abdc6..5e07618bee 100644 --- a/config/initializers/domain_config.rb +++ b/config/initializers/domain_config.rb @@ -1,4 +1,4 @@ -require "yaml" +require 'yaml' # there are unit tests for this file. Have a look at elektra/spec/initializers/domain_config_spec.rb @@ -16,11 +16,14 @@ class DomainConfig elsif File.exist?("#{File.dirname(__FILE__)}/../support/domain_config.yaml") @@domain_config_file = YAML.load_file("#{File.dirname(__FILE__)}/../support/domain_config.yaml") || {} else - raise "DomainConfig: No domain config file found" + raise 'DomainConfig: No domain config file found' end - def initialize(scoped_domain_name) + update_domain(scoped_domain_name) + end + + def update_domain(scoped_domain_name) @scoped_domain_name = scoped_domain_name # initialize the domain config using the find_config method @domain_config = find_config(@@domain_config_file, scoped_domain_name) @@ -30,38 +33,38 @@ def initialize(scoped_domain_name) # this method allows to hide plugins for specific domains # it is used for building the services menu (config/navigation/*) def plugin_hidden?(name) - return @domain_config.fetch("disabled_plugins", []).include?(name.to_s) + @domain_config.fetch('disabled_plugins', []).include?(name.to_s) end def feature_hidden?(name) - return @domain_config.fetch("disabled_features", []).include?(name.to_s) + @domain_config.fetch('disabled_features', []).include?(name.to_s) end def floating_ip_networks # fetch floating_ip_networks from config # and replace #{domain_name} in each network name with the scoped domain name - return @domain_config.fetch("floating_ip_networks", []).map do |network_name| - network_name.gsub('%DOMAIN_NAME%',@scoped_domain_name) + @domain_config.fetch('floating_ip_networks', []).map do |network_name| + network_name.gsub('%DOMAIN_NAME%', @scoped_domain_name) end end def dns_c_subdomain? - return @domain_config.fetch("dns_c_subdomain", false) + @domain_config.fetch('dns_c_subdomain', false) end def check_cidr_range? - return @domain_config.fetch("check_cidr_range", true) + @domain_config.fetch('check_cidr_range', true) end - + private def find_config(domains_config, scoped_domain_name) # to allow to match the last matching domain config, we reverse the list - # it allows us to define a config matching all domains at the top and then + # it allows us to define a config matching all domains at the top and then # override it with a more specific config. - domains_config.fetch("domains", []).reverse.find do |domain_config| + domains_config.fetch('domains', []).reverse.find do |domain_config| regex_pattern = Regexp.new(domain_config.fetch('regex', '')) scoped_domain_name =~ regex_pattern end || {} end -end \ No newline at end of file +end diff --git a/config/initializers/sprockets_processor.rb b/config/initializers/sprockets_processor.rb index 96dd23cbfb..c448e8714b 100644 --- a/config/initializers/sprockets_processor.rb +++ b/config/initializers/sprockets_processor.rb @@ -6,12 +6,12 @@ def self.call(input) # check if the file is a _widget.js file # copy the file to the public/assets folder if filename.end_with?('_widget.js') - # without the digest in the file name - path = File.join(Rails.public_path, 'assets', File.basename(filename)) - # Ensure the path directory exists - FileUtils.mkdir_p(path) + target_dir = File.join(Rails.public_path, 'assets') + target_path = File.join(target_dir, File.basename(filename)) + # Ensure the target directory exists + FileUtils.mkdir_p(target_dir) # Copy the file - FileUtils.cp(filename, path) + FileUtils.cp(filename, target_path) end nil end