diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb index 69af6f437..51f4a19f4 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 @@ -186,11 +188,11 @@ class WikiController < ApplicationController respond_to do |format| format.html do 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}) end format.api do 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 @@ -224,13 +226,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 @@ -300,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 @@ -346,13 +348,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 fe95eea47..c1241f42f 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -209,7 +209,7 @@ module ApplicationHelper lambda do |wiki_page| link_to( wiki_page.pretty_title, - project_wiki_page_path(wiki_page.project, wiki_page.title) + url_for({:controller => 'wiki', :action => 'show', project_id: wiki_page.project, id: wiki_page.title}) ) end } @@ -296,11 +296,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( @@ -959,13 +954,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 =~ /^(.+?)\#(.+)$/ @@ -973,7 +969,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 04a9253c3..7ce50d57c 100644 --- a/app/helpers/wiki_helper.rb +++ b/app/helpers/wiki_helper.rb @@ -63,15 +63,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 fe0419fdd..ea9746bc1 100644 --- a/app/models/wiki_page.rb +++ b/app/models/wiki_page.rb @@ -85,7 +85,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) @@ -210,7 +216,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 c501d6e28..1aa887cca 100644 --- a/app/views/wiki/edit.html.erb +++ b/app/views/wiki/edit.html.erb @@ -63,7 +63,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 1c25f2203..cf7644db2 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -300,7 +300,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 40c1d5f50..7667dda65 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -206,6 +206,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 70b4942b8..95b097562 100644 --- a/lib/redmine.rb +++ b/lib/redmine.rb @@ -279,6 +279,15 @@ Redmine::MenuManager.map :application_menu do |menu| end, :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 07c57354e..a5f4677dc 100644 --- a/lib/redmine/wiki_formatting/macros.rb +++ b/lib/redmine/wiki_formatting/macros.rb @@ -207,8 +207,7 @@ module Redmine else raise t(:error_childpages_macro_no_argument) end - raise t(:error_page_not_found) if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project) - + raise t(:error_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 @@ -218,8 +217,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 t(:error_page_not_found) if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project) - + raise t(:error_page_not_found) if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project, global: page.wiki.global?) @included_wiki_pages ||= [] raise t(:error_circular_inclusion) if @included_wiki_pages.include?(page.id)