Last active
June 1, 2023 09:03
-
-
Save keineahnung2345/4f5eee59079128645cad8aa88016fa77 to your computer and use it in GitHub Desktop.
Global wiki feature for Redmine 4.1.1 and 4.1.2, adapted from draft-feature-1040-r20825.patch by Mizuki ISHIKAWA on https://www.redmine.org/issues/1040#note-66
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb | |
index 4a88079..e7496fb 100644 | |
--- a/app/controllers/attachments_controller.rb | |
+++ b/app/controllers/attachments_controller.rb | |
@@ -158,8 +158,10 @@ class AttachmentsController < ApplicationController | |
@attachment.destroy | |
end | |
+ container = @attachment.try(:container) || @container | |
respond_to do |format| | |
- format.html { redirect_to_referer_or project_path(@project) } | |
+ # redirect to project or global wiki page | |
+ format.html { redirect_to_referer_or @project ? project_path(@project) : wiki_index_path(container)} | |
format.js | |
format.api { render_api_ok } | |
end | |
diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb | |
index 423f94f..49c372f 100644 | |
--- a/app/controllers/wiki_controller.rb | |
+++ b/app/controllers/wiki_controller.rb | |
@@ -33,7 +33,7 @@ | |
# TODO: still being worked on | |
class WikiController < ApplicationController | |
default_search_scope :wiki_pages | |
- before_action :find_wiki, :authorize | |
+ before_action :find_wiki, :authorize_global | |
before_action :find_existing_or_new_page, :only => [:show, :edit] | |
before_action :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy, :destroy_version] | |
before_action :find_attachments, :only => [:preview] | |
@@ -41,11 +41,13 @@ class WikiController < ApplicationController | |
helper :attachments | |
include AttachmentsHelper | |
+ include WikiHelper | |
helper :watchers | |
include Redmine::Export::PDF | |
# List of pages, sorted alphabetically and by parent (hierarchy) | |
def index | |
+ authorize if params[:project_id] | |
load_pages_for_index | |
respond_to do |format| | |
@@ -64,7 +66,7 @@ class WikiController < ApplicationController | |
def new | |
@page = WikiPage.new(:wiki => @wiki, :title => params[:title]) | |
- unless User.current.allowed_to?(:edit_wiki_pages, @project) | |
+ unless @wiki.allowed_to_permission?(:view_wiki_edits) | |
render_403 | |
return | |
end | |
@@ -72,7 +74,7 @@ class WikiController < ApplicationController | |
@page.title = '' unless editable? | |
@page.validate | |
if @page.errors[:title].blank? | |
- path = project_wiki_page_path(@project, @page.title, :parent => params[:parent]) | |
+ path = wiki_page_action_path('show', @page, {:parent => params[:parent]}) | |
respond_to do |format| | |
format.html { redirect_to path } | |
format.js { render :js => "window.location = #{path.to_json}" } | |
@@ -83,13 +85,13 @@ class WikiController < ApplicationController | |
# display a page (in editing mode if it doesn't exist) | |
def show | |
- if params[:version] && !User.current.allowed_to?(:view_wiki_edits, @project) | |
+ if params[:version] && !@wiki.allowed_to_permission?(:view_wiki_edits) | |
deny_access | |
return | |
end | |
@content = @page.content_for_version(params[:version]) | |
if @content.nil? | |
- if User.current.allowed_to?(:edit_wiki_pages, @project) && editable? && !api_request? | |
+ if @wiki.allowed_to_permission?(:view_wiki_edits) && editable? && !api_request? | |
edit | |
render :action => 'edit' | |
else | |
@@ -185,11 +187,11 @@ class WikiController < ApplicationController | |
respond_to do |format| | |
format.html { | |
anchor = @section ? "section-#{@section}" : nil | |
- redirect_to project_wiki_page_path(@project, @page.title, :anchor => anchor) | |
+ redirect_to wiki_page_action_path('show', @page, {:anchor => anchor}) | |
} | |
format.api { | |
if was_new_page | |
- render :action => 'show', :status => :created, :location => project_wiki_page_path(@project, @page.title) | |
+ render :action => 'show', :status => :created, :location => wiki_page_action_path('show', @page) | |
else | |
render_api_ok | |
end | |
@@ -222,13 +224,13 @@ class WikiController < ApplicationController | |
@page.safe_attributes = params[:wiki_page] | |
if request.post? && @page.save | |
flash[:notice] = l(:notice_successful_update) | |
- redirect_to project_wiki_page_path(@page.project, @page.title) | |
+ redirect_to wiki_page_action_path('show', @page) | |
end | |
end | |
def protect | |
@page.update_attribute :protected, params[:protected] | |
- redirect_to project_wiki_page_path(@project, @page.title) | |
+ redirect_to wiki_page_action_path('show', @page) | |
end | |
# show page history | |
@@ -284,7 +286,13 @@ class WikiController < ApplicationController | |
end | |
@page.destroy | |
respond_to do |format| | |
- format.html { redirect_to project_wiki_index_path(@project) } | |
+ format.html { | |
+ if @project | |
+ redirect_to project_wiki_index_path(@project) | |
+ else | |
+ redirect_to wiki_index_path | |
+ end | |
+ } | |
format.api { render_api_ok } | |
end | |
end | |
@@ -294,7 +302,7 @@ class WikiController < ApplicationController | |
if content = @page.content.versions.find_by_version(params[:version]) | |
content.destroy | |
- redirect_to_referer_or history_project_wiki_page_path(@project, @page.title) | |
+ redirect_to_referer_or wiki_page_action_path('history', @page) | |
else | |
render_404 | |
end | |
@@ -339,13 +347,22 @@ class WikiController < ApplicationController | |
private | |
def find_wiki | |
- @project = Project.find(params[:project_id]) | |
- @wiki = @project.wiki | |
+ if params[:project_id] | |
+ @project = Project.find(params[:project_id]) | |
+ @wiki = @project.wiki | |
+ else | |
+ @wiki = Wiki.find_by(:project_id => nil) | |
+ Wiki.create(:project => nil, :start_page => 'Wiki') if @wiki.nil? | |
+ end | |
render_404 unless @wiki | |
rescue ActiveRecord::RecordNotFound | |
render_404 | |
end | |
+ def global_wiki? | |
+ @wiki.project.nil? | |
+ end | |
+ | |
# Finds the requested page or a new page if it doesn't exist | |
def find_existing_or_new_page | |
@page = @wiki.find_or_new_page(params[:id]) | |
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb | |
index e8284a0..c1f97a6 100644 | |
--- a/app/helpers/application_helper.rb | |
+++ b/app/helpers/application_helper.rb | |
@@ -200,7 +200,7 @@ module ApplicationHelper | |
'Project' => -> (project) { link_to_project(project) }, | |
'User' => -> (user) { link_to_user(user) }, | |
'Version' => -> (version) { link_to_version(version) }, | |
- 'WikiPage' => -> (wiki_page) { link_to(wiki_page.pretty_title, project_wiki_page_path(wiki_page.project, wiki_page.title)) } | |
+ 'WikiPage' => -> (wiki_page) { link_to(wiki_page.pretty_title, url_for({:controller => 'wiki', :action => 'show', project_id: wiki_page.project, id: wiki_page.title})) } | |
} | |
def link_to_record(record) | |
@@ -270,10 +270,6 @@ module ApplicationHelper | |
end | |
end | |
- def wiki_page_path(page, options={}) | |
- url_for({:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title}.merge(options)) | |
- end | |
- | |
def thumbnail_tag(attachment) | |
thumbnail_size = Setting.thumbnails_size.to_i | |
link_to( | |
@@ -889,13 +885,14 @@ module ApplicationHelper | |
next link_to(title.present? ? title.html_safe : h(page), url, :class => 'wiki-page') | |
end | |
- if page =~ /^([^\:]+)\:(.*)$/ | |
+ if page =~ /^(.*)\:(.*)$/ | |
identifier, page = $1, $2 | |
link_project = Project.find_by_identifier(identifier) || Project.find_by_name(identifier) | |
title ||= identifier if page.blank? | |
end | |
- | |
- if link_project && link_project.wiki && User.current.allowed_to?(:view_wiki_pages, link_project) | |
+ wiki = Wiki.find_by(:project => link_project) | |
+ if wiki && wiki.allowed_to_permission?(:view_wiki_pages) && | |
+ (link_project || (wiki.global? && link_project.nil?)) | |
# extract anchor | |
anchor = nil | |
if page =~ /^(.+?)\#(.+)$/ | |
@@ -903,7 +900,7 @@ module ApplicationHelper | |
end | |
anchor = sanitize_anchor_name(anchor) if anchor.present? | |
# check if page exists | |
- wiki_page = link_project.wiki.find_page(page) | |
+ wiki_page = wiki.find_page(page) | |
url = | |
if anchor.present? && wiki_page.present? && | |
(obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version)) && | |
diff --git a/app/helpers/wiki_helper.rb b/app/helpers/wiki_helper.rb | |
index 0a94073..1d777c0 100644 | |
--- a/app/helpers/wiki_helper.rb | |
+++ b/app/helpers/wiki_helper.rb | |
@@ -56,15 +56,23 @@ module WikiHelper | |
def wiki_page_edit_cancel_path(page) | |
if page.new_record? | |
if parent = page.parent | |
- project_wiki_page_path(parent.project, parent.title) | |
+ wiki_page_action_path('show', parent) | |
else | |
- project_wiki_index_path(page.project) | |
+ if page.project | |
+ project_wiki_index_path(page.project) | |
+ else | |
+ wiki_index_path | |
+ end | |
end | |
else | |
- project_wiki_page_path(page.project, page.title) | |
+ wiki_page_action_path('show', page) | |
end | |
end | |
+ def wiki_page_action_path(action_name, page=nil, options={}) | |
+ url_for({:controller => 'wiki', :action => action_name, :project_id => (page.wiki.project if page), :id => (page.title if page)}.merge(options)) | |
+ end | |
+ | |
def wiki_content_update_info(content) | |
l(:label_updated_time_by, :author => link_to_user(content.author), :age => time_tag(content.updated_on)).html_safe | |
end | |
diff --git a/app/models/wiki.rb b/app/models/wiki.rb | |
index ed4331f..f18b01b 100644 | |
--- a/app/models/wiki.rb | |
+++ b/app/models/wiki.rb | |
@@ -34,7 +34,7 @@ class Wiki < ActiveRecord::Base | |
safe_attributes 'start_page' | |
def visible?(user=User.current) | |
- !user.nil? && user.allowed_to?(:view_wiki_pages, project) | |
+ !user.nil? && user.allowed_to?(:view_wiki_pages, project, global: self.global?) | |
end | |
# Returns the wiki page that acts as the sidebar content | |
@@ -85,12 +85,13 @@ class Wiki < ActiveRecord::Base | |
# Wiki.find_page("foo:bar") | |
def self.find_page(title, options = {}) | |
project = options[:project] | |
- if title.to_s =~ %r{^([^\:]+)\:(.*)$} | |
+ if title.to_s =~ %r{^(.*):(.*)$} | |
project_identifier, title = $1, $2 | |
project = Project.find_by_identifier(project_identifier) || Project.find_by_name(project_identifier) | |
end | |
- if project && project.wiki | |
- page = project.wiki.find_page(title) | |
+ wiki = project_identifier.present? ? (project && project.wiki) : Wiki.find_by(project: nil) | |
+ if wiki | |
+ page = wiki.find_page(title) | |
if page && page.content | |
page | |
end | |
@@ -105,4 +106,16 @@ class Wiki < ActiveRecord::Base | |
title = (title.slice(0..0).upcase + (title.slice(1..-1) || '')) if title | |
title | |
end | |
+ | |
+ def global? | |
+ self.project.nil? | |
+ end | |
+ | |
+ def allowed_to_permission?(permission, user=User.current) | |
+ user.allowed_to?(permission, self.project, :global => self.global?) | |
+ end | |
+ | |
+ def allowed_to_action?(action) | |
+ User.current.allowed_to?({:controller => 'wiki', :action => action}, self.project, :global => self.global?) | |
+ end | |
end | |
diff --git a/app/models/wiki_content.rb b/app/models/wiki_content.rb | |
index d38c5ca..82dc458 100644 | |
--- a/app/models/wiki_content.rb | |
+++ b/app/models/wiki_content.rb | |
@@ -53,7 +53,7 @@ class WikiContent < ActiveRecord::Base | |
end | |
def notified_users | |
- project.notified_users.reject {|user| !visible?(user)} | |
+ self.global? ? [] : project.notified_users.reject {|user| !visible?(user)} | |
end | |
# Returns the mail addresses of users that should be notified | |
@@ -79,6 +79,10 @@ class WikiContent < ActiveRecord::Base | |
end | |
end | |
+ def global? | |
+ self.project.nil? | |
+ end | |
+ | |
private | |
def create_version | |
diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb | |
index c4da80f..6a139f0 100644 | |
--- a/app/models/wiki_page.rb | |
+++ b/app/models/wiki_page.rb | |
@@ -62,10 +62,10 @@ class WikiPage < ActiveRecord::Base | |
DEFAULT_PROTECTED_PAGES = %w(sidebar) | |
safe_attributes 'parent_id', 'parent_title', 'title', 'redirect_existing_links', 'wiki_id', | |
- :if => lambda {|page, user| page.new_record? || user.allowed_to?(:rename_wiki_pages, page.project)} | |
+ :if => lambda {|page, user| page.new_record? || user.allowed_to?(:rename_wiki_pages, page.project, global: page.wiki.global?)} | |
safe_attributes 'is_start_page', | |
- :if => lambda {|page, user| user.allowed_to?(:manage_wiki, page.project)} | |
+ :if => lambda {|page, user| user.allowed_to?(:manage_wiki, page.project, global: page.wiki.global?)} | |
safe_attributes 'deleted_attachment_ids', | |
:if => lambda {|page, user| page.attachments_deletable?(user)} | |
@@ -78,7 +78,13 @@ class WikiPage < ActiveRecord::Base | |
end | |
def visible?(user=User.current) | |
- !user.nil? && user.allowed_to?(:view_wiki_pages, project) | |
+ !user.nil? && | |
+ user.allowed_to?(:view_wiki_pages, self.project, global: self.wiki.global?) | |
+ end | |
+ | |
+ def attachments_visible?(user=User.current) | |
+ (respond_to?(:visible?) ? visible?(user) : true) && | |
+ user.allowed_to?(self.class.attachable_options[:view_permission], self.project, global: self.wiki.global?) | |
end | |
def title=(value) | |
@@ -203,7 +209,7 @@ class WikiPage < ActiveRecord::Base | |
# Returns true if usr is allowed to edit the page, otherwise false | |
def editable_by?(usr) | |
- !protected? || usr.allowed_to?(:protect_wiki_pages, wiki.project) | |
+ !protected? || self.wiki.allowed_to_permission?(:protect_wiki_pages, usr) | |
end | |
def attachments_deletable?(usr=User.current) | |
diff --git a/app/views/wiki/_new_modal.html.erb b/app/views/wiki/_new_modal.html.erb | |
index 108c6ad..02f014b 100644 | |
--- a/app/views/wiki/_new_modal.html.erb | |
+++ b/app/views/wiki/_new_modal.html.erb | |
@@ -1,7 +1,7 @@ | |
<h3 class="title"><%=l(:label_wiki_page_new)%></h3> | |
<%= labelled_form_for :page, @page, | |
- :url => new_project_wiki_page_path(@project), | |
+ :url => wiki_page_action_path('new', @page), | |
:method => 'post', | |
:remote => true do |f| %> | |
diff --git a/app/views/wiki/annotate.html.erb b/app/views/wiki/annotate.html.erb | |
index 1b48f5d..7738c80 100644 | |
--- a/app/views/wiki/annotate.html.erb | |
+++ b/app/views/wiki/annotate.html.erb | |
@@ -6,8 +6,8 @@ | |
<%= wiki_page_breadcrumb(@page) %> | |
-<%= title [@page.pretty_title, project_wiki_page_path(@page.project, @page.title, :version => nil)], | |
- [l(:label_history), history_project_wiki_page_path(@page.project, @page.title)], | |
+<%= title [@page.pretty_title, wiki_page_action_path('show', @page, {:version => nil})], | |
+ [l(:label_history), wiki_page_action_path('history', @page)], | |
"#{l(:label_version)} #{@annotate.content.version}" %> | |
<p> | |
diff --git a/app/views/wiki/date_index.html.erb b/app/views/wiki/date_index.html.erb | |
index 274f19a..f4975f6 100644 | |
--- a/app/views/wiki/date_index.html.erb | |
+++ b/app/views/wiki/date_index.html.erb | |
@@ -1,6 +1,6 @@ | |
<div class="contextual"> | |
<% if User.current.allowed_to?(:edit_wiki_pages, @project) %> | |
-<%= link_to l(:label_wiki_page_new), new_project_wiki_page_path(@project), :remote => true, :class => 'icon icon-add' %> | |
+<%= link_to l(:label_wiki_page_new), wiki_page_action_path('new', @page), :remote => true, :class => 'icon icon-add' %> | |
<% end %> | |
<%= watcher_link(@wiki, User.current) %> | |
<% if User.current.allowed_to?(:manage_wiki, @project) %> | |
diff --git a/app/views/wiki/diff.html.erb b/app/views/wiki/diff.html.erb | |
index 765e51a..153af89 100644 | |
--- a/app/views/wiki/diff.html.erb | |
+++ b/app/views/wiki/diff.html.erb | |
@@ -5,8 +5,8 @@ | |
<%= wiki_page_breadcrumb(@page) %> | |
-<%= title [@page.pretty_title, project_wiki_page_path(@page.project, @page.title, :version => nil)], | |
- [l(:label_history), history_project_wiki_page_path(@page.project, @page.title)], | |
+<%= title [@page.pretty_title, wiki_page_action_path('show', @page, {:version => nil})], | |
+ [l(:label_history), wiki_page_action_path('history', @page)], | |
"#{l(:label_revision)} #{@diff.content_to.version}" %> | |
<p> | |
diff --git a/app/views/wiki/edit.html.erb b/app/views/wiki/edit.html.erb | |
index 0e1c23c..a86a1e9 100644 | |
--- a/app/views/wiki/edit.html.erb | |
+++ b/app/views/wiki/edit.html.erb | |
@@ -64,7 +64,7 @@ | |
<%= submit_tag l(:button_save) %> | |
<%= link_to l(:button_cancel), wiki_page_edit_cancel_path(@page) %> | |
</p> | |
-<%= wikitoolbar_for 'content_text', preview_project_wiki_page_path(:project_id => @project, :id => @page.title) %> | |
+<%= wikitoolbar_for 'content_text', wiki_page_action_path('preview', @page) %> | |
<% end %> | |
<% content_for :header_tags do %> | |
diff --git a/app/views/wiki/history.html.erb b/app/views/wiki/history.html.erb | |
index 3e638a8..dea9c58 100644 | |
--- a/app/views/wiki/history.html.erb | |
+++ b/app/views/wiki/history.html.erb | |
@@ -1,6 +1,6 @@ | |
<%= wiki_page_breadcrumb(@page) %> | |
-<%= title [@page.pretty_title, project_wiki_page_path(@page.project, @page.title, :version => nil)], l(:label_history) %> | |
+<%= title [@page.pretty_title, wiki_page_action_path('show', @page, {:version => nil})], l(:label_history) %> | |
<%= form_tag({:controller => 'wiki', :action => 'diff', | |
:project_id => @page.project, :id => @page.title}, | |
@@ -31,7 +31,7 @@ | |
<td class="comments"><%= ver.comments %></td> | |
<td class="buttons"> | |
<%= link_to l(:button_annotate), :action => 'annotate', :id => @page.title, :version => ver.version %> | |
- <%= delete_link wiki_page_path(@page, :version => ver.version) if User.current.allowed_to?(:delete_wiki_pages, @page.project) && @version_count > 1 %> | |
+ <%= delete_link wiki_page_action_path('show', @page, {:version => ver.version}) if @page.wiki.allowed_to_permission?(:delete_wiki_pages) && @version_count > 1 %> | |
</td> | |
</tr> | |
<% line_num += 1 %> | |
diff --git a/app/views/wiki/index.html.erb b/app/views/wiki/index.html.erb | |
index bb60868..df8234f 100644 | |
--- a/app/views/wiki/index.html.erb | |
+++ b/app/views/wiki/index.html.erb | |
@@ -1,6 +1,6 @@ | |
<div class="contextual"> | |
<% if User.current.allowed_to?(:edit_wiki_pages, @project) %> | |
-<%= link_to l(:label_wiki_page_new), new_project_wiki_page_path(@project), :remote => true, :class => 'icon icon-add' %> | |
+<%= link_to l(:label_wiki_page_new), wiki_page_action_path('new'), :remote => true, :class => 'icon icon-add' %> | |
<% end %> | |
<%= watcher_link(@wiki, User.current) %> | |
<% if User.current.allowed_to?(:manage_wiki, @project) %> | |
diff --git a/app/views/wiki/new.html.erb b/app/views/wiki/new.html.erb | |
index d067420..1ad2f78 100644 | |
--- a/app/views/wiki/new.html.erb | |
+++ b/app/views/wiki/new.html.erb | |
@@ -1,7 +1,7 @@ | |
<%= title l(:label_wiki_page_new) %> | |
<%= labelled_form_for :page, @page, | |
- :url => new_project_wiki_page_path(@project) do |f| %> | |
+ :url => wiki_page_action_path('new', @page) do |f| %> | |
<%= render_error_messages @page.errors.full_messages_for(:title) %> | |
diff --git a/app/views/wiki/rename.html.erb b/app/views/wiki/rename.html.erb | |
index 13fb41a..46e9295 100644 | |
--- a/app/views/wiki/rename.html.erb | |
+++ b/app/views/wiki/rename.html.erb | |
@@ -13,7 +13,7 @@ | |
<p><%= f.check_box :is_start_page, :label => :field_start_page, :disabled => @page.is_start_page %></p> | |
<% end %> | |
<p><%= f.check_box :redirect_existing_links %></p> | |
-<% if @page.safe_attribute? 'wiki_id' %> | |
+<% if @page.safe_attribute? 'wiki_id' && !@page.wiki.global? %> | |
<p><%= f.select :wiki_id, wiki_page_wiki_options_for_select(@page), :label => :label_project %></p> | |
<% end %> | |
<p><%= f.select :parent_id, | |
@@ -30,7 +30,7 @@ | |
<%= javascript_tag do %> | |
$('#wiki_page_wiki_id').change(function() { | |
$.ajax({ | |
- url: '<%= rename_project_wiki_page_path(@wiki, :format => 'js') %>', | |
+ url: '<%= wiki_page_action_path('rename', @page, {:format => 'js'}) %>', | |
type: 'get', | |
data: { 'wiki_page[wiki_id]': $('#wiki_page_wiki_id').val() } | |
}); | |
diff --git a/app/views/wiki/show.html.erb b/app/views/wiki/show.html.erb | |
index a710496..856793f 100644 | |
--- a/app/views/wiki/show.html.erb | |
+++ b/app/views/wiki/show.html.erb | |
@@ -2,27 +2,27 @@ | |
<% if @editable %> | |
<% if @content.current_version? %> | |
- <%= link_to_if_authorized(l(:button_edit), {:action => 'edit', :id => @page.title}, :class => 'icon icon-edit', :accesskey => accesskey(:edit)) %> | |
+ <%= link_to(l(:button_edit), {:action => 'edit', :id => @page.title}, :class => 'icon icon-edit', :accesskey => accesskey(:edit)) if @page.wiki.allowed_to_action?('edit') %> | |
<%= watcher_link(@page, User.current) %> | |
<% end %> | |
<% end %> | |
<%= actions_dropdown do %> | |
- <%= link_to_if_authorized(l(:label_history), {:action => 'history', :id => @page.title}, :class => 'icon icon-history') %> | |
+ <%= link_to(l(:label_history), {:action => 'history', :id => @page.title}, :class => 'icon icon-history') if @page.wiki.allowed_to_action?('history') %> | |
<% if @editable %> | |
<% if @content.current_version? %> | |
- <%= 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') %> | |
- <%= 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') %> | |
+ <%= link_to(l(:button_lock), {:action => 'protect', :id => @page.title, :protected => 1}, :method => :post, :class => 'icon icon-lock') if !@page.protected? && @page.wiki.allowed_to_action?('protect') %> | |
+ <%= link_to(l(:button_unlock), {:action => 'protect', :id => @page.title, :protected => 0}, :method => :post, :class => 'icon icon-unlock') if @page.protected? && @page.wiki.allowed_to_action?('protect') %> | |
+ <%= link_to(l(:button_rename), {:action => 'rename', :id => @page.title}, :class => 'icon icon-move') if @page.wiki.allowed_to_action?('rename') %> | |
+ <%= link_to(l(:button_delete), {:action => 'destroy', :id => @page.title}, :method => :delete, :data => {:confirm => l(:text_are_you_sure)}, :class => 'icon icon-del') if @page.wiki.allowed_to_action?('destroy') %> | |
<% else %> | |
- <%= link_to_if_authorized(l(:button_rollback), {:action => 'edit', :id => @page.title, :version => @content.version }, :class => 'icon icon-cancel') %> | |
+ <%= link_to(l(:button_rollback), {:action => 'edit', :id => @page.title, :version => @content.version }, :class => 'icon icon-cancel') if @page.wiki.allowed_to_action?('edit') %> | |
<% end %> | |
<% end %> | |
- <% if User.current.allowed_to?(:edit_wiki_pages, @project) %> | |
- <%= link_to l(:label_wiki_page_new), new_project_wiki_page_path(@project, :parent => @page.title), :remote => true, :class => 'icon icon-add' %> | |
+ <% if @page.wiki.allowed_to_permission?(:edit_wiki_pages) %> | |
+ <%= link_to l(:label_wiki_page_new), wiki_page_action_path('new', @page, {:parent => @page.title}), :remote => true, :class => 'icon icon-add' %> | |
<% end %> | |
<% end %> | |
</div> | |
@@ -30,8 +30,8 @@ | |
<%= wiki_page_breadcrumb(@page) %> | |
<% unless @content.current_version? %> | |
- <%= title [@page.pretty_title, project_wiki_page_path(@page.project, @page.title, :version => nil)], | |
- [l(:label_history), history_project_wiki_page_path(@page.project, @page.title)], | |
+ <%= title [@page.pretty_title, wiki_page_action_path('show', @page, {:version => nil})], | |
+ [l(:label_history), wiki_page_action_path('history', @page)], | |
"#{l(:label_revision)} #{@content.version}" %> | |
<p> | |
diff --git a/config/routes.rb b/config/routes.rb | |
index d8e5fd7..68f316f 100644 | |
--- a/config/routes.rb | |
+++ b/config/routes.rb | |
@@ -183,6 +183,30 @@ Rails.application.routes.draw do | |
get 'wiki/:id/:version/annotate', :to => 'wiki#annotate' | |
get 'wiki/:id/:version/diff', :to => 'wiki#diff' | |
end | |
+ match 'wiki/index', :controller => 'wiki', :action => 'index', :via => :get | |
+ resources :wiki, :except => [:index, :create, :show], :as => 'wiki_page' do | |
+ member do | |
+ get 'wiki', :as => 'show_wiki_page' | |
+ get 'rename' | |
+ post 'rename' | |
+ get 'history' | |
+ get 'diff' | |
+ match 'preview', :via => [:post, :put, :patch] | |
+ post 'protect' | |
+ post 'add_attachment' | |
+ end | |
+ collection do | |
+ get 'export' | |
+ get 'date_index' | |
+ post 'new' | |
+ end | |
+ end | |
+ match 'wiki', :controller => 'wiki', :action => 'show', :via => :get | |
+ get 'wiki/:id/:version', :to => 'wiki#show', :constraints => {:version => /\d+/} | |
+ delete 'wiki/:id/:version', :to => 'wiki#destroy_version' | |
+ get 'wiki/:id/:version/annotate', :to => 'wiki#annotate' | |
+ get 'wiki/:id/:version/diff', :to => 'wiki#diff' | |
+ match 'wiki/:id/destroy', :to => 'wikis#destroy', :via => [:get, :post] | |
resources :issues do | |
member do | |
diff --git a/db/migrate/20200729083854_allow_wiki_project_id_to_be_nil.rb b/db/migrate/20200729083854_allow_wiki_project_id_to_be_nil.rb | |
new file mode 100644 | |
index 0000000..7312d08 | |
--- /dev/null | |
+++ b/db/migrate/20200729083854_allow_wiki_project_id_to_be_nil.rb | |
@@ -0,0 +1,8 @@ | |
+class AllowWikiProjectIdToBeNil < ActiveRecord::Migration[5.2] | |
+ def up | |
+ change_column_null :wikis, :project_id, true | |
+ end | |
+ def down | |
+ change_column_null :wikis, :project_id, false | |
+ end | |
+end | |
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 4df4b6a..3ca03a3 100644 | |
--- a/lib/plugins/acts_as_attachable/lib/acts_as_attachable.rb | |
+++ b/lib/plugins/acts_as_attachable/lib/acts_as_attachable.rb | |
@@ -58,7 +58,7 @@ module Redmine | |
def attachments_deletable?(user=User.current) | |
(respond_to?(:visible?) ? visible?(user) : true) && | |
- user.allowed_to?(self.class.attachable_options[:delete_permission], self.project) | |
+ user.allowed_to?(self.class.attachable_options[:delete_permission], self.project, :global => ((self.is_a? WikiPage) ? self.wiki.global?: false)) | |
end | |
def saved_attachments | |
diff --git a/lib/plugins/acts_as_searchable/lib/acts_as_searchable.rb b/lib/plugins/acts_as_searchable/lib/acts_as_searchable.rb | |
index 83fa394..6ff8347 100644 | |
--- a/lib/plugins/acts_as_searchable/lib/acts_as_searchable.rb | |
+++ b/lib/plugins/acts_as_searchable/lib/acts_as_searchable.rb | |
@@ -196,6 +196,22 @@ module Redmine | |
if projects | |
scope = scope.where("#{searchable_options[:project_key]} IN (?)", projects.map(&:id)) | |
+ elsif scope.table_name == "wiki_pages" && options[:params][:wiki_pages] == "1" | |
+ # including global wiki | |
+ scope_global_wikis = WikiPage.joins(:wiki).where("wikis.project_id is null") | |
+ # Method 1: | |
+ # ArgumentError (Relation passed to #or must be structurally compatible. Incompatible values: [:joins]) | |
+ #scope = scope.or(scope_global_wikis) | |
+ # Method 2: | |
+ # TypeError (Cannot visit WikiPage::ActiveRecord_Relation) | |
+ #wiki_page_table = WikiPage.arel_table | |
+ #combined = Arel::Nodes::UnionAll.new(scope, scope_global_wikis) | |
+ #scope = WikiPage.from(Arel::Nodes::As.new(combined, wiki_page_table)) | |
+ # Method 3: | |
+ # https://stackoverflow.com/questions/57491185/obtain-union-all-result-in-activerecord | |
+ # https://stackoverflow.com/questions/17331862/converting-an-array-of-objects-to-activerecordrelation | |
+ scope_array = WikiPage.find_by_sql("#{scope.to_sql} UNION #{scope_global_wikis.to_sql}") | |
+ scope = WikiPage.where(id: scope_array.map(&:id)).joins(:content) #.joins({:wiki => :project}) | |
end | |
scope | |
end | |
diff --git a/lib/redmine.rb b/lib/redmine.rb | |
index 9ecca63..58da75b 100644 | |
--- a/lib/redmine.rb | |
+++ b/lib/redmine.rb | |
@@ -242,6 +242,15 @@ Redmine::MenuManager.map :application_menu do |menu| | |
EnabledModule.exists?(:project => Project.visible, :name => :news) | |
}, | |
:caption => :label_news_plural | |
+ menu.push( | |
+ :wiki, | |
+ {:controller => 'wiki', :action => 'show'}, | |
+ :if => | |
+ Proc.new do | |
+ User.current.allowed_to?(:view_wiki_pages, nil, :global => true) | |
+ end, | |
+ :caption => :label_wiki | |
+ ) | |
end | |
Redmine::MenuManager.map :admin_menu do |menu| | |
diff --git a/lib/redmine/wiki_formatting/macros.rb b/lib/redmine/wiki_formatting/macros.rb | |
index 99eac68..c2d03b7 100644 | |
--- a/lib/redmine/wiki_formatting/macros.rb | |
+++ b/lib/redmine/wiki_formatting/macros.rb | |
@@ -205,7 +205,7 @@ module Redmine | |
else | |
raise 'With no argument, this macro can be called from wiki pages only.' | |
end | |
- raise 'Page not found' if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project) | |
+ raise 'Page not found' if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project, global: page.wiki.global?) | |
pages = page.self_and_descendants(options[:depth]).group_by(&:parent_id) | |
render_page_hierarchy(pages, options[:parent] ? page.parent_id : page.id) | |
end | |
@@ -215,7 +215,7 @@ module Redmine | |
"{{include(projectname:Foo)}} -- to include a page of a specific project wiki" | |
macro :include do |obj, args| | |
page = Wiki.find_page(args.first.to_s, :project => @project) | |
- raise 'Page not found' if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project) | |
+ raise 'Page not found' if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project, global: page.wiki.global?) | |
@included_wiki_pages ||= [] | |
raise 'Circular inclusion detected' if @included_wiki_pages.include?(page.id) | |
@included_wiki_pages << page.id |
Usage: download it as global_wiki_redmine-4.1.1.patch4
, and then git apply --reject global_wiki_redmine-4.1.1.patch
, then RAILS_ENV=production bundle exec rake db:migrate
.
revision 6: make global wiki searchable
superseded by global_wiki_redmine-5.0.5.patch
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
revision 5: attachments_deletable? Fix for non-WikiPage class