From c17b42509b2a79e53d19facfa00fcc16ec401cf9 Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Fri, 22 Dec 2023 02:08:53 +0000 Subject: [PATCH] Fixes attachments functionality for (custom) plugins broken since fix for CVE-2022-44030 by adding a dynamic routing constraint which can be modified by plugins (#39862). Patch by @jkraemer. git-svn-id: https://svn.redmine.org/redmine/trunk@22551 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- config/routes.rb | 4 +++- .../lib/acts_as_attachable.rb | 24 +++++++++++++++++++ .../plugins/redmine_test_plugin_foo/init.rb | 2 ++ test/integration/routing/plugins_test.rb | 5 ++++ 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index 6176fdfae..12be7b3ec 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -317,7 +317,9 @@ Rails.application.routes.draw do get 'attachments/download/:id', :to => 'attachments#download', :id => /\d+/ get 'attachments/thumbnail/:id(/:size)', :to => 'attachments#thumbnail', :id => /\d+/, :size => /\d+/, :as => 'thumbnail' resources :attachments, :only => [:show, :update, :destroy] - constraints object_type: /(issues|versions|news|messages|wiki_pages|projects|documents|journals)/ do + + # register plugin object types with ObjectTypeConstraint.register_object_type(PluginModel.name.underscore.pluralize') + constraints Redmine::Acts::Attachable::ObjectTypeConstraint do get 'attachments/:object_type/:object_id/edit', :to => 'attachments#edit_all', :as => :object_attachments_edit patch 'attachments/:object_type/:object_id', :to => 'attachments#update_all', :as => :object_attachments get 'attachments/:object_type/:object_id/download', :to => 'attachments#download_all', :as => :object_attachments_download diff --git a/lib/plugins/acts_as_attachable/lib/acts_as_attachable.rb b/lib/plugins/acts_as_attachable/lib/acts_as_attachable.rb index 4a069980d..9c09a7870 100644 --- a/lib/plugins/acts_as_attachable/lib/acts_as_attachable.rb +++ b/lib/plugins/acts_as_attachable/lib/acts_as_attachable.rb @@ -20,6 +20,30 @@ module Redmine module Acts module Attachable + + class ObjectTypeConstraint + cattr_accessor :object_types + + self.object_types = Concurrent::Set.new(%w[ + issues versions news messages wiki_pages projects documents journals + ]) + + class << self + def matches?(request) + request.path_parameters[:object_type] =~ param_expression + end + + def register_object_type(type) + object_types << type + @param_expression = nil + end + + def param_expression + @param_expression ||= Regexp.new("^(#{object_types.join("|")})$") + end + end + end + def self.included(base) base.extend ClassMethods end diff --git a/test/fixtures/plugins/redmine_test_plugin_foo/init.rb b/test/fixtures/plugins/redmine_test_plugin_foo/init.rb index bdbff5d95..990e7c2d8 100644 --- a/test/fixtures/plugins/redmine_test_plugin_foo/init.rb +++ b/test/fixtures/plugins/redmine_test_plugin_foo/init.rb @@ -5,6 +5,8 @@ Redmine::Plugin.register :redmine_test_plugin_foo do version '0.0.1' end +Redmine::Acts::Attachable::ObjectTypeConstraint.register_object_type('plugin_articles') + Pathname(__dir__).glob("app/**/*.rb").sort.each do |path| require path end diff --git a/test/integration/routing/plugins_test.rb b/test/integration/routing/plugins_test.rb index 0124e759f..aeefa43bd 100644 --- a/test/integration/routing/plugins_test.rb +++ b/test/integration/routing/plugins_test.rb @@ -43,5 +43,10 @@ class RoutingPluginsTest < Redmine::RoutingTest should_route 'GET /plugin_articles' => 'plugin_articles#index' should_route 'GET /bar_plugin_articles' => 'bar_plugin_articles#index' assert_equal("/bar_plugin_articles", plugin_articles_path) + should_route( + 'GET /attachments/plugin_articles/12/edit' => 'attachments#edit_all', + object_id: '12', + object_type: 'plugin_articles' + ) end end -- 2.39.5