diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb index b3d6e8efd..c47a5719f 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| @@ -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 @@ -297,7 +299,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 @@ -341,13 +343,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 8cb07bb23..feae6ed6e 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -203,7 +203,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) @@ -286,10 +286,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( @@ -926,13 +922,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 =~ /^(.+?)\#(.+)$/ @@ -940,7 +937,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 6690b04fc..c7971775b 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 8173fb212..d32164520 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_page.rb b/app/models/wiki_page.rb index 4fc4d4706..52e6f9573 100644 --- a/app/models/wiki_page.rb +++ b/app/models/wiki_page.rb @@ -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) 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 108c6ad88..02f014bc6 100644 --- a/app/views/wiki/_new_modal.html.erb +++ b/app/views/wiki/_new_modal.html.erb @@ -1,7 +1,7 @@

<%=l(:label_wiki_page_new)%>

<%= 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 1b48f5db8..7738c8006 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}" %>

diff --git a/app/views/wiki/date_index.html.erb b/app/views/wiki/date_index.html.erb index 274f19a8a..f4975f639 100644 --- a/app/views/wiki/date_index.html.erb +++ b/app/views/wiki/date_index.html.erb @@ -1,6 +1,6 @@

<% 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 765e51a0a..153af89aa 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}" %>

diff --git a/app/views/wiki/edit.html.erb b/app/views/wiki/edit.html.erb index 0e1c23cc4..a86a1e92e 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) %>

-<%= 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 3e638a880..dea9c581a 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 @@ <%= ver.comments %> <%= 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 %> <% line_num += 1 %> diff --git a/app/views/wiki/index.html.erb b/app/views/wiki/index.html.erb index bb6086874..df8234f94 100644 --- a/app/views/wiki/index.html.erb +++ b/app/views/wiki/index.html.erb @@ -1,6 +1,6 @@
<% 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 d0674202d..1ad2f7862 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 13fb41a70..f83fc3771 100644 --- a/app/views/wiki/rename.html.erb +++ b/app/views/wiki/rename.html.erb @@ -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 a7104967d..4d442b734 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' %> + <%= link_to l(:label_wiki_page_new), wiki_page_action_path('new', @page, {:parent => @page.title}), :remote => true, :class => 'icon icon-add' %> <% end %> <% end %>
@@ -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}" %>

diff --git a/config/locales/ja.yml b/config/locales/ja.yml index dab4f1399..a972bc005 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -299,7 +299,7 @@ ja: field_attr_firstname: 名の属性 field_attr_lastname: 姓の属性 field_attr_mail: メールアドレスの属性 - field_onthefly: ユーザーが存在しなければ作成 + field_onthefly: あわせてユーザーを作成 field_start_date: 開始日 field_done_ratio: 進捗率 field_auth_source: 認証方式 diff --git a/config/routes.rb b/config/routes.rb index 03071fad9..3ce646f3d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -184,6 +184,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 000000000..7312d089d --- /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/redmine.rb b/lib/redmine.rb index 668a65da2..87796c3d3 100644 --- a/lib/redmine.rb +++ b/lib/redmine.rb @@ -242,6 +242,11 @@ 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 { + User.current.allowed_to?(:view_wiki_pages, nil, :global => true) + }, + :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 c34e404e2..5de44774f 100644 --- a/lib/redmine/wiki_formatting/macros.rb +++ b/lib/redmine/wiki_formatting/macros.rb @@ -206,7 +206,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 @@ -216,7 +216,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