summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/views/queries/_form.html.erb2
-rw-r--r--app/views/workflows/edit.html.erb4
-rw-r--r--config/routes.rb2
-rw-r--r--doc/CHANGELOG21
-rw-r--r--lib/redmine/version.rb2
-rw-r--r--public/stylesheets/application.css2
-rw-r--r--test/functional/queries_controller_test.rb40
-rw-r--r--test/integration/api_test/attachments_test.rb2
-rw-r--r--test/integration/attachments_test.rb10
-rw-r--r--test/integration/routing/attachments_test.rb2
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'