diff options
-rw-r--r-- | app/views/queries/_form.html.erb | 2 | ||||
-rw-r--r-- | app/views/workflows/edit.html.erb | 4 | ||||
-rw-r--r-- | config/routes.rb | 2 | ||||
-rw-r--r-- | doc/CHANGELOG | 21 | ||||
-rw-r--r-- | lib/redmine/version.rb | 2 | ||||
-rw-r--r-- | public/stylesheets/application.css | 2 | ||||
-rw-r--r-- | test/functional/queries_controller_test.rb | 40 | ||||
-rw-r--r-- | test/integration/api_test/attachments_test.rb | 2 | ||||
-rw-r--r-- | test/integration/attachments_test.rb | 10 | ||||
-rw-r--r-- | test/integration/routing/attachments_test.rb | 2 |
10 files changed, 79 insertions, 8 deletions
diff --git a/app/views/queries/_form.html.erb b/app/views/queries/_form.html.erb index 1c302fe76..75a20248a 100644 --- a/app/views/queries/_form.html.erb +++ b/app/views/queries/_form.html.erb @@ -30,7 +30,7 @@ <% unless @query.is_a?(ProjectQuery) %> <p><label for="query_is_for_all"><%=l(:field_is_for_all)%></label> - <%= check_box_tag 'query_is_for_all', 1, @query.project.nil?, :class => (User.current.admin? ? '' : 'disable-unless-private') %></p> + <%= check_box_tag 'query_is_for_all', 1, @query.project.nil?, :disabled => (!@query.new_record? && @query.project.nil?), :class => (User.current.admin? ? '' : 'disable-unless-private') %></p> <% end %> <% unless params[:calendar] %> diff --git a/app/views/workflows/edit.html.erb b/app/views/workflows/edit.html.erb index df4507be2..adb1996cd 100644 --- a/app/views/workflows/edit.html.erb +++ b/app/views/workflows/edit.html.erb @@ -40,7 +40,7 @@ <%= render :partial => 'form', :locals => {:name => 'always', :workflows => @workflows['always']} %> <fieldset class="collapsible" style="padding: 0; margin-top: 0.5em;"> - <legend onclick="toggleFieldset(this);" class="icon icon-collapsed"><%= l(:label_additional_workflow_transitions_for_author) %></legend> + <legend onclick="toggleFieldset(this);" class="icon icon-<%= @workflows['author'].present? ? "expanded" : "collapsed" %>"><%= l(:label_additional_workflow_transitions_for_author) %></legend> <div id="author_workflows" style="margin: 0.5em 0 0.5em 0;"> <%= render :partial => 'form', :locals => {:name => 'author', :workflows => @workflows['author']} %> </div> @@ -48,7 +48,7 @@ <%= javascript_tag "hideFieldset($('#author_workflows'))" unless @workflows['author'].present? %> <fieldset class="collapsible" style="padding: 0;"> - <legend onclick="toggleFieldset(this);" class="icon icon-collapsed"><%= l(:label_additional_workflow_transitions_for_assignee) %></legend> + <legend onclick="toggleFieldset(this);" class="icon icon-<%= @workflows['assignee'].present? ? "expanded" : "collapsed" %>"><%= l(:label_additional_workflow_transitions_for_assignee) %></legend> <div id="assignee_workflows" style="margin: 0.5em 0 0.5em 0;"> <%= render :partial => 'form', :locals => {:name => 'assignee', :workflows => @workflows['assignee']} %> </div> diff --git a/config/routes.rb b/config/routes.rb index d5296b3c3..0457ff1ef 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -313,7 +313,7 @@ Rails.application.routes.draw do # additional routes for having the file name at the end of url get 'attachments/:id/:filename', :to => 'attachments#show', :id => /\d+/, :filename => /.*/, :as => 'named_attachment', :format => 'html' - get 'attachments/download/:id/:filename', :to => 'attachments#download', :id => /\d+/, :filename => /.*/, :as => 'download_named_attachment' + get 'attachments/download/:id/:filename', :to => 'attachments#download', :id => /\d+/, :filename => /.*/, :as => 'download_named_attachment', :format => 'html' 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] diff --git a/doc/CHANGELOG b/doc/CHANGELOG index ae7ac9aaf..e620a9bb6 100644 --- a/doc/CHANGELOG +++ b/doc/CHANGELOG @@ -4,6 +4,27 @@ Redmine - project management software Copyright (C) 2006- Jean-Philippe Lang https://www.redmine.org/ +== 2025-03-10 v5.1.7 + +=== [Code cleanup/refactoring] + +* Defect #42200: InlineAutocompleteSystemTest login test fails randomly +* Patch #42244: Fix random failures in IssuesTest#test_bulk_copy due to StaleElementReferenceError + +=== [Gems support] + +* Defect #42245: 5.1-stable: Redmine fails to start with error: Unknown database adapter `"mysql2"` found in config/database.yml + +=== [No category] + +* Feature #30069: Use GitHub Actions as a secondary CI solution to run tests through the existing mirroring + +=== [Security] +* Defect #42326: Stored Cross-Site Scripting (XSS) in macros +* Defect #42352: ProjectQuery leaks details of private projects +* Defect #42194: /my/account does not correctly enforce sudo mode +* Patch #42333: Update Nokogiri to 1.18.3 + == 2025-01-29 v5.1.6 === [Code cleanup/refactoring] diff --git a/lib/redmine/version.rb b/lib/redmine/version.rb index 1c4dc4ae5..ab2f54558 100644 --- a/lib/redmine/version.rb +++ b/lib/redmine/version.rb @@ -7,7 +7,7 @@ module Redmine module VERSION MAJOR = 5 MINOR = 1 - TINY = 6 + TINY = 7 # Branch values: # * official release: nil diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index 009424993..01bd7a5ab 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -476,7 +476,7 @@ div.square { .contextual {float:right; white-space: nowrap; line-height:1.4em;margin:5px 0px; padding-left: 10px; font-size:0.9em;} .contextual .icon {padding-top: 2px; padding-bottom: 3px;} .contextual input, .contextual select {font-size:0.9em;} -.message .contextual { margin-top: 0; } +.message .contextual, #comments .contextual { margin-top: 0; } .splitcontent {overflow: auto; display: flex; flex-wrap: wrap;} .splitcontentleft {flex: 1; margin-right: 5px;} diff --git a/test/functional/queries_controller_test.rb b/test/functional/queries_controller_test.rb index 4ee2155ff..ab3dcf531 100644 --- a/test/functional/queries_controller_test.rb +++ b/test/functional/queries_controller_test.rb @@ -986,4 +986,44 @@ class QueriesControllerTest < Redmine::ControllerTest assert_include ["Development", "10"], json assert_include ["Inactive Activity", "14"], json end + + def test_new_query_is_for_all_checkbox_not_disabled + @request.session[:user_id] = 1 + get :new + assert_response :success + # Verify that the "For all projects" checkbox is not disabled when creating a new query + assert_select 'input[name=query_is_for_all][type=checkbox][checked]:not([disabled])' + end + + def test_new_project_query_is_for_all_checkbox_not_disabled + @request.session[:user_id] = 1 + get(:new, :params => {:project_id => 1}) + assert_response :success + # Verify that the checkbox is not disabled when creating a new query within a project + assert_select 'input[name=query_is_for_all][type=checkbox]:not([checked]):not([disabled])' + end + + def test_edit_global_query_is_for_all_checkbox_disabled + @request.session[:user_id] = 1 + # Create a global query (project_id = nil) + query = IssueQuery.create!(:name => 'test_global_query', :user_id => 1, :project_id => nil) + + get(:edit, :params => {:id => query.id}) + assert_response :success + + # Verify that the "For all projects" checkbox is disabled when editing an existing global query + assert_select 'input[name=query_is_for_all][type=checkbox][checked][disabled]' + end + + def test_edit_project_query_is_for_all_checkbox_not_disabled + @request.session[:user_id] = 1 + # Create a project-specific query + query = IssueQuery.create!(:name => 'test_project_query', :user_id => 1, :project_id => 1) + + get(:edit, :params => {:id => query.id}) + assert_response :success + + # Verify that the checkbox is not disabled when editing a project-specific query + assert_select 'input[name=query_is_for_all][type=checkbox]:not([checked]):not([disabled])' + end end diff --git a/test/integration/api_test/attachments_test.rb b/test/integration/api_test/attachments_test.rb index d07e22a66..32c08a067 100644 --- a/test/integration/api_test/attachments_test.rb +++ b/test/integration/api_test/attachments_test.rb @@ -63,7 +63,7 @@ class Redmine::ApiTest::AttachmentsTest < Redmine::ApiTest::Base test "GET /attachments/download/:id/:filename should deny access without credentials" do get '/attachments/download/7/archive.zip' - assert_response 401 + assert_response 302 end test "GET /attachments/thumbnail/:id should return the thumbnail" do diff --git a/test/integration/attachments_test.rb b/test/integration/attachments_test.rb index fc64df3ee..e0a78ca9b 100644 --- a/test/integration/attachments_test.rb +++ b/test/integration/attachments_test.rb @@ -267,6 +267,16 @@ class AttachmentsTest < Redmine::IntegrationTest end end + def test_unauthorized_named_download_link_should_redirect_to_login + with_settings login_required: '1' do + get "/attachments/download/1" + assert_redirected_to "/login?back_url=http%3A%2F%2Fwww.example.com%2Fattachments%2Fdownload%2F1" + + get "/attachments/download/1/error281.txt" + assert_redirected_to "/login?back_url=http%3A%2F%2Fwww.example.com%2Fattachments%2Fdownload%2F1%2Ferror281.txt" + end + end + private def ajax_upload(filename, content, attachment_id=1) diff --git a/test/integration/routing/attachments_test.rb b/test/integration/routing/attachments_test.rb index 15e61635b..18b411f99 100644 --- a/test/integration/routing/attachments_test.rb +++ b/test/integration/routing/attachments_test.rb @@ -26,7 +26,7 @@ class RoutingAttachmentsTest < Redmine::RoutingTest should_route 'GET /attachments/1/filename.txt' => 'attachments#show', :id => '1', :filename => 'filename.txt', :format => 'html' should_route 'GET /attachments/download/1' => 'attachments#download', :id => '1' - should_route 'GET /attachments/download/1/filename.ext' => 'attachments#download', :id => '1', :filename => 'filename.ext' + should_route 'GET /attachments/download/1/filename.ext' => 'attachments#download', :id => '1', :filename => 'filename.ext', :format => 'html' should_route 'GET /attachments/thumbnail/1' => 'attachments#thumbnail', :id => '1' should_route 'GET /attachments/thumbnail/1/200' => 'attachments#thumbnail', :id => '1', :size => '200' |