diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb index 2669c60e6..4b634fd0b 100644 --- a/app/controllers/wiki_controller.rb +++ b/app/controllers/wiki_controller.rb @@ -118,6 +118,7 @@ def show @content.current_version? && Redmine::WikiFormatting.supports_section_edit? + @redirects_to_self = WikiRedirect.where(:redirects_to => @page.title, :redirects_to_wiki_id => @page.wiki_id) respond_to do |format| format.html format.api diff --git a/app/controllers/wiki_redirects_controller.rb b/app/controllers/wiki_redirects_controller.rb new file mode 100644 index 000000000..ef1c2aaa0 --- /dev/null +++ b/app/controllers/wiki_redirects_controller.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +# Redmine - project management software +# Copyright (C) 2006-2020 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +class WikiRedirectsController < ApplicationController + before_action :find_wiki_redirect, :authorize + + def destroy + if @wiki_redirect.destroy + flash[:notice] = l(:notice_successful_delete) + redirect_to project_wiki_page_path(@page.project, @page.title) + end + end + + private + + def find_wiki_redirect + @project = Project.find(params[:project_id]) + @page = Wiki.find_page(params[:wiki_page_id], project: @project) + @wiki_redirect=WikiRedirect.where(redirects_to: @page.title).find(params[:id]) + render_404 unless @wiki_redirect + rescue ActiveRecord::RecordNotFound + render_404 + end +end diff --git a/app/views/wiki/show.html.erb b/app/views/wiki/show.html.erb index 6a0245809..d6db7e477 100644 --- a/app/views/wiki/show.html.erb +++ b/app/views/wiki/show.html.erb @@ -15,6 +15,11 @@ <%= link_to_if_authorized(l(:button_lock), {:action => 'protect', :id => @page.title, :protected => 1}, :method => :post, :class => 'icon icon-lock') if !@page.protected? %> <%= link_to_if_authorized(l(:button_unlock), {:action => 'protect', :id => @page.title, :protected => 0}, :method => :post, :class => 'icon icon-unlock') if @page.protected? %> <%= link_to_if_authorized(l(:button_rename), {:action => 'rename', :id => @page.title}, :class => 'icon icon-move') %> + <% if User.current.allowed_to?(:rename_wiki_pages, @project) %> + <% @redirects_to_self.map { |redirect| %> + <%= link_to(l(:button_delete_redirect, :page_title => WikiPage.pretty_title(redirect.title)), {:controller => 'wiki_redirects', :action => 'destroy', :project_id => @project.identifier, :wiki_page_id => @page.title, :id => redirect.id}, :method => :delete, :class => 'icon icon-link-break') %> + <% } %> + <% end %> <%= link_to_if_authorized(l(:button_delete), {:action => 'destroy', :id => @page.title}, :method => :delete, :data => {:confirm => l(:text_are_you_sure)}, :class => 'icon icon-del') %> <% else %> <%= link_to_if_authorized(l(:button_rollback), {:action => 'edit', :id => @page.title, :version => @content.version }, :class => 'icon icon-cancel') %> diff --git a/config/locales/de.yml b/config/locales/de.yml index 50d986bc8..b7b23bfcf 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -177,6 +177,7 @@ de: button_create_and_continue: Anlegen und weiter button_delete: Löschen button_delete_my_account: Mein Benutzerkonto löschen + button_delete_redirect: "Lösche Umleitung von %{page_title}" button_download: Herunterladen button_edit: Bearbeiten button_edit_associated_wikipage: "Zugehörige Wikiseite bearbeiten: %{page_title}" diff --git a/config/locales/en.yml b/config/locales/en.yml index f9064c866..35e39290e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1176,6 +1176,7 @@ en: button_unarchive: Unarchive button_reset: Reset button_rename: Rename + button_delete_redirect: "Delete redirect from %{page_title}" button_change_password: Change password button_copy: Copy button_copy_and_follow: Copy and follow diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 0215e7555..73b8406cf 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -852,6 +852,7 @@ ja: button_unarchive: アーカイブ解除 button_reset: リセット button_rename: 名前変更 + button_delete_redirect: "%{page_title}からのリダイレクトを削除" button_change_password: パスワード変更 button_copy: コピー button_copy_and_follow: コピー後表示 diff --git a/config/routes.rb b/config/routes.rb index 00eadf679..0fa40a74c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -191,6 +191,7 @@ match 'wiki/index', :controller => 'wiki', :action => 'index', :via => :get resources :wiki, :except => [:index, :create], :as => 'wiki_page' do + resources :redirects, controller: 'wiki_redirects', only: :destroy member do get 'rename' post 'rename' diff --git a/lib/redmine/preparation.rb b/lib/redmine/preparation.rb index c51ecfdb9..962c688db 100644 --- a/lib/redmine/preparation.rb +++ b/lib/redmine/preparation.rb @@ -121,7 +121,7 @@ def self.prepare map.permission :view_wiki_edits, {:wiki => [:history, :diff, :annotate]}, :read => true map.permission :export_wiki_pages, {:wiki => [:export]}, :read => true map.permission :edit_wiki_pages, :wiki => [:new, :edit, :update, :preview, :add_attachment], :attachments => :upload - map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member + map.permission :rename_wiki_pages, {:wiki => :rename, :wiki_redirects => :destroy}, :require => :member map.permission :delete_wiki_pages, {:wiki => [:destroy, :destroy_version]}, :require => :member map.permission :delete_wiki_pages_attachments, {} map.permission :view_wiki_page_watchers, {}, :read => true diff --git a/test/functional/wiki_controller_test.rb b/test/functional/wiki_controller_test.rb index 3765ac867..19e20870f 100644 --- a/test/functional/wiki_controller_test.rb +++ b/test/functional/wiki_controller_test.rb @@ -233,6 +233,49 @@ def test_show_protected_page_shoud_show_locked_badge end end + def test_show_delete_redirect_links + @request.session[:user_id] = 2 + + wiki_page = WikiPage.find_by(title: 'CookBook_documentation') + wiki_page.title = 'Old_Cookbook' + wiki_page.save + + wiki_page.title = 'New_Cookbook' + wiki_page.save + + cookbook_doc_redirect = WikiRedirect.find_by(title: 'CookBook_documentation', redirects_to: 'New_Cookbook') + old_cookbook_redirect = WikiRedirect.find_by(title: 'Old_Cookbook', redirects_to: 'New_Cookbook') + + get :show, :params => {:project_id => 'ecookbook', :id => 'New_Cookbook'} + + assert_select '.drdn-items' do + assert_select 'a.icon-link-break[href=?]', + "/projects/ecookbook/wiki/New_Cookbook/redirects/#{cookbook_doc_redirect.id}", + text: 'Delete redirect from CookBook documentation' + assert_select 'a.icon-link-break[href=?]', + "/projects/ecookbook/wiki/New_Cookbook/redirects/#{old_cookbook_redirect.id}", + text: 'Delete redirect from Old Cookbook' + end + end + + def test_hide_delete_redirect_links_without_permission + @request.session[:user_id] = 2 + + wiki_page = WikiPage.find_by(title: 'CookBook_documentation') + wiki_page.title = 'Old_Cookbook' + wiki_page.save + + project = wiki_page.wiki.project + role = User.find(2).members.find_by(project: project).roles.first + role.remove_permission! :rename_wiki_pages + + get :show, :params => {:project_id => 'ecookbook', :id => 'Old_Cookbook'} + + assert_select '.drdn-items' do + assert_select 'a.icon-link-break', count: 0 + end + end + def test_get_new @request.session[:user_id] = 2 diff --git a/test/functional/wiki_redirects_controller_test.rb b/test/functional/wiki_redirects_controller_test.rb new file mode 100644 index 000000000..7949ec3b5 --- /dev/null +++ b/test/functional/wiki_redirects_controller_test.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +# Redmine - project management software +# Copyright (C) 2006-2020 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require File.expand_path('../../test_helper', __FILE__) + +class WikiRedirectsControllerTest < Redmine::ControllerTest + fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles, + :enabled_modules, :wikis, :wiki_pages, :wiki_contents, + :wiki_content_versions, :attachments, + :issues, :issue_statuses, :trackers + + def setup + User.current = nil + @request.session[:user_id] = 1 + end + + def test_destroy + wiki_page = WikiPage.find(2) + old_title = wiki_page.title + wiki_page.title = 'Test' + wiki_page.save + + wiki_redirect = WikiRedirect.find_by(title: old_title, redirects_to: 'Test') + + delete :destroy, params: {id: wiki_redirect.id, project_id: wiki_page.wiki.project_id, wiki_page_id: 'Test'} + + assert_redirected_to '/projects/ecookbook/wiki/Test' + assert_equal 'Successful deletion.', flash[:notice] + assert_not WikiRedirect.exists?(id: wiki_redirect.id) + end + + def test_destroy_without_permission + @request.session[:user_id] = User.generate!.id + + wiki_page = WikiPage.find(2) + old_title = wiki_page.title + wiki_page.title = 'Test' + wiki_page.save + + wiki_redirect = WikiRedirect.find_by(title: old_title, redirects_to: 'Test') + + delete :destroy, params: {id: wiki_redirect.id, project_id: wiki_page.wiki.project_id, wiki_page_id: 'Test'} + + assert_response :forbidden + assert WikiRedirect.exists?(id: wiki_redirect.id) + end + + def test_invalid_redirect_should_respond_with_404 + wiki_page = WikiPage.find(1) + old_title = wiki_page.title + wiki_page.title = 'New_Title' + wiki_page.save + + other_wiki_page = WikiPage.find(2) + other_wiki_page.title = 'Other_New_Title' + other_wiki_page.save + + wiki_redirect = WikiRedirect.find_by(title: old_title, redirects_to: 'New_Title') + + delete :destroy, params: {id: wiki_redirect.id, project_id: other_wiki_page.wiki.project_id, wiki_page_id: 'Other_New_Title'} + + assert_response :not_found + assert WikiRedirect.exists?(id: wiki_redirect.id) + end +end