Project

General

Profile

Feature #1040 » draft-feature-1040.patch

Mizuki ISHIKAWA, 2020-07-30 09:05

View differences:

app/controllers/wiki_controller.rb
33 33
# TODO: still being worked on
34 34
class WikiController < ApplicationController
35 35
  default_search_scope :wiki_pages
36
  before_action :find_wiki, :authorize
36
  before_action :find_wiki, :authorize_global
37 37
  before_action :find_existing_or_new_page, :only => [:show, :edit]
38 38
  before_action :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy, :destroy_version]
39 39
  before_action :find_attachments, :only => [:preview]
......
41 41

  
42 42
  helper :attachments
43 43
  include AttachmentsHelper
44
  include WikiHelper
44 45
  helper :watchers
45 46
  include Redmine::Export::PDF
46 47

  
47 48
  # List of pages, sorted alphabetically and by parent (hierarchy)
48 49
  def index
50
    authorize if params[:project_id]
49 51
    load_pages_for_index
50 52

  
51 53
    respond_to do |format|
......
72 74
      @page.title = '' unless editable?
73 75
      @page.validate
74 76
      if @page.errors[:title].blank?
75
        path = project_wiki_page_path(@project, @page.title, :parent => params[:parent])
77
        path = wiki_page_action_path('show', @page, {:parent => params[:parent]})
76 78
        respond_to do |format|
77 79
          format.html { redirect_to path }
78 80
          format.js   { render :js => "window.location = #{path.to_json}" }
......
83 85

  
84 86
  # display a page (in editing mode if it doesn't exist)
85 87
  def show
86
    if params[:version] && !User.current.allowed_to?(:view_wiki_edits, @project)
88
    if params[:version] && !@wiki.allowed_to_permission?(:view_wiki_edits)
87 89
      deny_access
88 90
      return
89 91
    end
90 92
    @content = @page.content_for_version(params[:version])
91 93
    if @content.nil?
92
      if User.current.allowed_to?(:edit_wiki_pages, @project) && editable? && !api_request?
94
      if @wiki.allowed_to_permission?(:view_wiki_edits) && editable? && !api_request?
93 95
        edit
94 96
        render :action => 'edit'
95 97
      else
......
185 187
      respond_to do |format|
186 188
        format.html {
187 189
          anchor = @section ? "section-#{@section}" : nil
188
          redirect_to project_wiki_page_path(@project, @page.title, :anchor => anchor)
190
          redirect_to wiki_page_action_path('show', @page, {:anchor => anchor})
189 191
        }
190 192
        format.api {
191 193
          if was_new_page
192
            render :action => 'show', :status => :created, :location => project_wiki_page_path(@project, @page.title)
194
            render :action => 'show', :status => :created, :location => wiki_page_action_path('show', @page)
193 195
          else
194 196
            render_api_ok
195 197
          end
......
222 224
    @page.safe_attributes = params[:wiki_page]
223 225
    if request.post? && @page.save
224 226
      flash[:notice] = l(:notice_successful_update)
225
      redirect_to project_wiki_page_path(@page.project, @page.title)
227
      redirect_to wiki_page_action_path('show', @page)
226 228
    end
227 229
  end
228 230

  
229 231
  def protect
230 232
    @page.update_attribute :protected, params[:protected]
231
    redirect_to project_wiki_page_path(@project, @page.title)
233
    redirect_to wiki_page_action_path('show', @page)
232 234
  end
233 235

  
234 236
  # show page history
......
297 299

  
298 300
    if content = @page.content.versions.find_by_version(params[:version])
299 301
      content.destroy
300
      redirect_to_referer_or history_project_wiki_page_path(@project, @page.title)
302
      redirect_to_referer_or wiki_page_action_path('history', @page)
301 303
    else
302 304
      render_404
303 305
    end
......
341 343
  private
342 344

  
343 345
  def find_wiki
344
    @project = Project.find(params[:project_id])
345
    @wiki = @project.wiki
346
    if params[:project_id]
347
      @project = Project.find(params[:project_id])
348
      @wiki = @project.wiki
349
    else
350
      @wiki = Wiki.find_by(:project_id => nil)
351
      Wiki.create(:project => nil, :start_page => 'Wiki') if @wiki.nil?
352
    end
346 353
    render_404 unless @wiki
347 354
  rescue ActiveRecord::RecordNotFound
348 355
    render_404
349 356
  end
350 357

  
358
  def global_wiki?
359
    @wiki.project.nil?
360
  end
361

  
351 362
  # Finds the requested page or a new page if it doesn't exist
352 363
  def find_existing_or_new_page
353 364
    @page = @wiki.find_or_new_page(params[:id])
app/helpers/application_helper.rb
203 203
    'Project'      => ->(project)      {link_to_project(project)},
204 204
    'User'         => ->(user)         {link_to_user(user)},
205 205
    'Version'      => ->(version)      {link_to_version(version)},
206
    'WikiPage'     => ->(wiki_page)    {link_to(wiki_page.pretty_title,project_wiki_page_path(wiki_page.project, wiki_page.title))}
206
    'WikiPage'     => ->(wiki_page)    {link_to(wiki_page.pretty_title, url_for({:controller => 'wiki', :action => 'show', project_id: wiki_page.project, id: wiki_page.title}))}
207 207
  }
208 208

  
209 209
  def link_to_record(record)
......
286 286
    end
287 287
  end
288 288

  
289
  def wiki_page_path(page, options={})
290
    url_for({:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title}.merge(options))
291
  end
292

  
293 289
  def thumbnail_tag(attachment)
294 290
    thumbnail_size = Setting.thumbnails_size.to_i
295 291
    link_to(
......
926 922
          next link_to(title.present? ? title.html_safe : h(page), url, :class => 'wiki-page')
927 923
        end
928 924

  
929
        if page =~ /^([^\:]+)\:(.*)$/
925
        if page =~ /^(.*)\:(.*)$/
930 926
          identifier, page = $1, $2
931 927
          link_project = Project.find_by_identifier(identifier) || Project.find_by_name(identifier)
932 928
          title ||= identifier if page.blank?
933 929
        end
934

  
935
        if link_project && link_project.wiki && User.current.allowed_to?(:view_wiki_pages, link_project)
930
        wiki = Wiki.find_by(:project => link_project)
931
        if wiki && wiki.allowed_to_permission?(:view_wiki_pages) &&
932
          (link_project || (wiki.global? && link_project.nil?))
936 933
          # extract anchor
937 934
          anchor = nil
938 935
          if page =~ /^(.+?)\#(.+)$/
......
940 937
          end
941 938
          anchor = sanitize_anchor_name(anchor) if anchor.present?
942 939
          # check if page exists
943
          wiki_page = link_project.wiki.find_page(page)
940
          wiki_page = wiki.find_page(page)
944 941
          url =
945 942
            if anchor.present? && wiki_page.present? &&
946 943
                 (obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version)) &&
app/helpers/wiki_helper.rb
56 56
  def wiki_page_edit_cancel_path(page)
57 57
    if page.new_record?
58 58
      if parent = page.parent
59
        project_wiki_page_path(parent.project, parent.title)
59
        wiki_page_action_path('show', parent)
60 60
      else
61
        project_wiki_index_path(page.project)
61
        if page.project
62
          project_wiki_index_path(page.project)
63
        else
64
          wiki_index_path
65
        end
62 66
      end
63 67
    else
64
      project_wiki_page_path(page.project, page.title)
68
      wiki_page_action_path('show', page)
65 69
    end
66 70
  end
67 71

  
72
  def wiki_page_action_path(action_name, page=nil, options={})
73
    url_for({:controller => 'wiki', :action => action_name, :project_id => (page.wiki.project if page), :id => (page.title if page)}.merge(options))
74
  end
75

  
68 76
  def wiki_content_update_info(content)
69 77
    l(:label_updated_time_by, :author => link_to_user(content.author), :age => time_tag(content.updated_on)).html_safe
70 78
  end
app/models/wiki.rb
34 34
  safe_attributes 'start_page'
35 35

  
36 36
  def visible?(user=User.current)
37
    !user.nil? && user.allowed_to?(:view_wiki_pages, project)
37
    !user.nil? && user.allowed_to?(:view_wiki_pages, project, global: self.global?)
38 38
  end
39 39

  
40 40
  # Returns the wiki page that acts as the sidebar content
......
85 85
  #   Wiki.find_page("foo:bar")
86 86
  def self.find_page(title, options = {})
87 87
    project = options[:project]
88
    if title.to_s =~ %r{^([^\:]+)\:(.*)$}
88
    if title.to_s =~ %r{^(.*):(.*)$}
89 89
      project_identifier, title = $1, $2
90 90
      project = Project.find_by_identifier(project_identifier) || Project.find_by_name(project_identifier)
91 91
    end
92
    if project && project.wiki
93
      page = project.wiki.find_page(title)
92
    wiki = project_identifier.present? ? (project && project.wiki) : Wiki.find_by(project: nil)
93
    if wiki
94
      page = wiki.find_page(title)
94 95
      if page && page.content
95 96
        page
96 97
      end
......
105 106
    title = (title.slice(0..0).upcase + (title.slice(1..-1) || '')) if title
106 107
    title
107 108
  end
109

  
110
  def global?
111
    self.project.nil?
112
  end
113

  
114
  def allowed_to_permission?(permission, user=User.current)
115
    user.allowed_to?(permission, self.project, :global => self.global?)
116
  end
117

  
118
  def allowed_to_action?(action)
119
    User.current.allowed_to?({:controller => 'wiki', :action => action}, self.project, :global => self.global?)
120
  end
108 121
end
app/models/wiki_page.rb
78 78
  end
79 79

  
80 80
  def visible?(user=User.current)
81
    !user.nil? && user.allowed_to?(:view_wiki_pages, project)
81
    !user.nil? &&
82
      user.allowed_to?(:view_wiki_pages, self.project, global: self.wiki.global?)
83
  end
84

  
85
  def attachments_visible?(user=User.current)
86
    (respond_to?(:visible?) ? visible?(user) : true) &&
87
      user.allowed_to?(self.class.attachable_options[:view_permission], self.project, global: self.wiki.global?)
82 88
  end
83 89

  
84 90
  def title=(value)
......
203 209

  
204 210
  # Returns true if usr is allowed to edit the page, otherwise false
205 211
  def editable_by?(usr)
206
    !protected? || usr.allowed_to?(:protect_wiki_pages, wiki.project)
212
    !protected? || self.wiki.allowed_to_permission?(:protect_wiki_pages)
207 213
  end
208 214

  
209 215
  def attachments_deletable?(usr=User.current)
app/views/wiki/_new_modal.html.erb
1 1
<h3 class="title"><%=l(:label_wiki_page_new)%></h3>
2 2

  
3 3
<%= labelled_form_for :page, @page,
4
            :url => new_project_wiki_page_path(@project),
4
            :url => wiki_page_action_path('new', @page),
5 5
            :method => 'post',
6 6
            :remote => true do |f| %>
7 7

  
app/views/wiki/annotate.html.erb
6 6

  
7 7
<%= wiki_page_breadcrumb(@page) %>
8 8

  
9
<%= title [@page.pretty_title, project_wiki_page_path(@page.project, @page.title, :version => nil)],
10
      [l(:label_history), history_project_wiki_page_path(@page.project, @page.title)],
9
<%= title [@page.pretty_title, wiki_page_action_path('show', @page, {:version => nil})],
10
      [l(:label_history), wiki_page_action_path('history', @page)],
11 11
      "#{l(:label_version)} #{@annotate.content.version}" %>
12 12

  
13 13
<p>
app/views/wiki/date_index.html.erb
1 1
<div class="contextual">
2 2
<% if User.current.allowed_to?(:edit_wiki_pages, @project) %>
3
<%= link_to l(:label_wiki_page_new), new_project_wiki_page_path(@project), :remote => true, :class => 'icon icon-add' %>
3
<%= link_to l(:label_wiki_page_new), wiki_page_action_path('new', @page), :remote => true, :class => 'icon icon-add' %>
4 4
<% end %>
5 5
<%= watcher_link(@wiki, User.current) %>
6 6
<% if User.current.allowed_to?(:manage_wiki, @project) %>
app/views/wiki/diff.html.erb
5 5

  
6 6
<%= wiki_page_breadcrumb(@page) %>
7 7

  
8
<%= title [@page.pretty_title, project_wiki_page_path(@page.project, @page.title, :version => nil)],
9
      [l(:label_history), history_project_wiki_page_path(@page.project, @page.title)],
8
<%= title [@page.pretty_title, wiki_page_action_path('show', @page, {:version => nil})],
9
      [l(:label_history), wiki_page_action_path('history', @page)],
10 10
      "#{l(:label_revision)} #{@diff.content_to.version}" %>
11 11

  
12 12
<p>
app/views/wiki/edit.html.erb
64 64
  <%= submit_tag l(:button_save) %>
65 65
  <%= link_to l(:button_cancel), wiki_page_edit_cancel_path(@page) %>
66 66
 </p>
67
<%= wikitoolbar_for 'content_text', preview_project_wiki_page_path(:project_id => @project, :id => @page.title) %>
67
<%= wikitoolbar_for 'content_text', wiki_page_action_path('preview', @page) %>
68 68
<% end %>
69 69

  
70 70
<% content_for :header_tags do %>
app/views/wiki/history.html.erb
1 1
<%= wiki_page_breadcrumb(@page) %>
2 2

  
3
<%= title [@page.pretty_title, project_wiki_page_path(@page.project, @page.title, :version => nil)], l(:label_history) %>
3
<%= title [@page.pretty_title, wiki_page_action_path('show', @page, {:version => nil})], l(:label_history) %>
4 4

  
5 5
<%= form_tag({:controller => 'wiki', :action => 'diff',
6 6
              :project_id => @page.project, :id => @page.title},
......
31 31
    <td class="comments"><%= ver.comments %></td>
32 32
    <td class="buttons">
33 33
      <%= link_to l(:button_annotate), :action => 'annotate', :id => @page.title, :version => ver.version %>
34
      <%= delete_link wiki_page_path(@page, :version => ver.version) if User.current.allowed_to?(:delete_wiki_pages, @page.project) && @version_count > 1 %>
34
      <%= delete_link wiki_page_action_path('show', @page, {:version => ver.version}) if @page.wiki.allowed_to_permission?(:delete_wiki_pages) && @version_count > 1 %>
35 35
    </td>
36 36
</tr>
37 37
<% line_num += 1 %>
app/views/wiki/index.html.erb
1 1
<div class="contextual">
2 2
<% if User.current.allowed_to?(:edit_wiki_pages, @project) %>
3
<%= link_to l(:label_wiki_page_new), new_project_wiki_page_path(@project), :remote => true, :class => 'icon icon-add' %>
3
<%= link_to l(:label_wiki_page_new), wiki_page_action_path('new'), :remote => true, :class => 'icon icon-add' %>
4 4
<% end %>
5 5
<%= watcher_link(@wiki, User.current) %>
6 6
<% if User.current.allowed_to?(:manage_wiki, @project) %>
app/views/wiki/new.html.erb
1 1
<%= title l(:label_wiki_page_new) %>
2 2

  
3 3
<%= labelled_form_for :page, @page,
4
            :url => new_project_wiki_page_path(@project) do |f| %>
4
            :url => wiki_page_action_path('new', @page) do |f| %>
5 5

  
6 6
  <%= render_error_messages @page.errors.full_messages_for(:title) %>
7 7

  
app/views/wiki/rename.html.erb
30 30
<%= javascript_tag do %>
31 31
$('#wiki_page_wiki_id').change(function() {
32 32
  $.ajax({
33
    url: '<%= rename_project_wiki_page_path(@wiki, :format => 'js') %>',
33
    url: '<%= wiki_page_action_path('rename', @page, {:format => 'js'}) %>',
34 34
    type: 'get',
35 35
    data: { 'wiki_page[wiki_id]': $('#wiki_page_wiki_id').val() }
36 36
  });
app/views/wiki/show.html.erb
2 2

  
3 3
<% if @editable %>
4 4
<% if @content.current_version? %>
5
  <%= link_to_if_authorized(l(:button_edit), {:action => 'edit', :id => @page.title}, :class => 'icon icon-edit', :accesskey => accesskey(:edit)) %>
5
  <%= link_to(l(:button_edit), {:action => 'edit', :id => @page.title}, :class => 'icon icon-edit', :accesskey => accesskey(:edit)) if @page.wiki.allowed_to_action?('edit') %>
6 6
  <%= watcher_link(@page, User.current) %>
7 7
<% end %>
8 8
<% end %>
9 9

  
10 10
  <%= actions_dropdown do %>
11
    <%= link_to_if_authorized(l(:label_history), {:action => 'history', :id => @page.title}, :class => 'icon icon-history') %>
11
    <%= link_to(l(:label_history), {:action => 'history', :id => @page.title}, :class => 'icon icon-history') if @page.wiki.allowed_to_action?('history') %>
12 12

  
13 13
    <% if @editable %>
14 14
    <% if @content.current_version? %>
15
      <%= link_to_if_authorized(l(:button_lock), {:action => 'protect', :id => @page.title, :protected => 1}, :method => :post, :class => 'icon icon-lock') if !@page.protected? %>
16
      <%= link_to_if_authorized(l(:button_unlock), {:action => 'protect', :id => @page.title, :protected => 0}, :method => :post, :class => 'icon icon-unlock') if @page.protected? %>
17
      <%= link_to_if_authorized(l(:button_rename), {:action => 'rename', :id => @page.title}, :class => 'icon icon-move') %>
18
      <%= 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') %>
15
      <%= 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') %>
16
      <%= 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') %>
17
      <%= link_to(l(:button_rename), {:action => 'rename', :id => @page.title}, :class => 'icon icon-move') if @page.wiki.allowed_to_action?('rename') %>
18
      <%= 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') %>
19 19
    <% else %>
20
      <%= link_to_if_authorized(l(:button_rollback), {:action => 'edit', :id => @page.title, :version => @content.version }, :class => 'icon icon-cancel') %>
20
      <%= link_to(l(:button_rollback), {:action => 'edit', :id => @page.title, :version => @content.version }, :class => 'icon icon-cancel') if @page.wiki.allowed_to_action?('edit') %>
21 21
    <% end %>
22 22
    <% end %>
23 23

  
24 24
    <% if User.current.allowed_to?(:edit_wiki_pages, @project) %>
25
      <%= link_to l(:label_wiki_page_new), new_project_wiki_page_path(@project, :parent => @page.title), :remote => true, :class => 'icon icon-add' %>
25
      <%= link_to l(:label_wiki_page_new), wiki_page_action_path('new', @page, {:parent => @page.title}), :remote => true, :class => 'icon icon-add' %>
26 26
    <% end %>
27 27
  <% end %>
28 28
</div>
......
30 30
<%= wiki_page_breadcrumb(@page) %>
31 31

  
32 32
<% unless @content.current_version? %>
33
  <%= title [@page.pretty_title, project_wiki_page_path(@page.project, @page.title, :version => nil)],
34
        [l(:label_history), history_project_wiki_page_path(@page.project, @page.title)],
33
  <%= title [@page.pretty_title, wiki_page_action_path('show', @page, {:version => nil})],
34
        [l(:label_history), wiki_page_action_path('history', @page)],
35 35
        "#{l(:label_revision)} #{@content.version}" %>
36 36

  
37 37
    <p>
config/locales/ja.yml
299 299
  field_attr_firstname: 名の属性
300 300
  field_attr_lastname: 姓の属性
301 301
  field_attr_mail: メールアドレスの属性
302
  field_onthefly: ユーザーが存在しなければ作成
302
  field_onthefly: あわせてユーザーを作成
303 303
  field_start_date: 開始日
304 304
  field_done_ratio: 進捗率
305 305
  field_auth_source: 認証方式
config/routes.rb
184 184
    get 'wiki/:id/:version/annotate', :to => 'wiki#annotate'
185 185
    get 'wiki/:id/:version/diff', :to => 'wiki#diff'
186 186
  end
187
  match 'wiki/index', :controller => 'wiki', :action => 'index', :via => :get
188
  resources :wiki, :except => [:index, :create, :show], :as => 'wiki_page' do
189
    member do
190
      get 'wiki', :as => 'show_wiki_page'
191
      get 'rename'
192
      post 'rename'
193
      get 'history'
194
      get 'diff'
195
      match 'preview', :via => [:post, :put, :patch]
196
      post 'protect'
197
      post 'add_attachment'
198
    end
199
    collection do
200
      get 'export'
201
      get 'date_index'
202
      post 'new'
203
    end
204
  end
205
  match 'wiki', :controller => 'wiki', :action => 'show', :via => :get
206
  get 'wiki/:id/:version', :to => 'wiki#show', :constraints => {:version => /\d+/}
207
  delete 'wiki/:id/:version', :to => 'wiki#destroy_version'
208
  get 'wiki/:id/:version/annotate', :to => 'wiki#annotate'
209
  get 'wiki/:id/:version/diff', :to => 'wiki#diff'
210
  match 'wiki/:id/destroy', :to => 'wikis#destroy', :via => [:get, :post]
187 211

  
188 212
  resources :issues do
189 213
    member do
db/migrate/20200729083854_allow_wiki_project_id_to_be_nil.rb
1
class AllowWikiProjectIdToBeNil < ActiveRecord::Migration[5.2]
2
  def up
3
   change_column_null :wikis, :project_id, true
4
  end
5
  def down
6
    change_column_null :wikis, :project_id, false
7
  end
8
end
lib/redmine.rb
242 242
                       EnabledModule.exists?(:project => Project.visible, :name => :news)
243 243
                   },
244 244
            :caption => :label_news_plural
245
  menu.push :wiki, {:controller => 'wiki', :action => 'show'},
246
            :if => Proc.new {
247
                     User.current.allowed_to?(:view_wiki_pages, nil, :global => true)
248
                   },
249
            :caption => :label_wiki
245 250
end
246 251

  
247 252
Redmine::MenuManager.map :admin_menu do |menu|
lib/redmine/wiki_formatting/macros.rb
206 206
        else
207 207
          raise 'With no argument, this macro can be called from wiki pages only.'
208 208
        end
209
        raise 'Page not found' if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project)
209
        raise 'Page not found' if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project, global: page.wiki.global?)
210 210
        pages = page.self_and_descendants(options[:depth]).group_by(&:parent_id)
211 211
        render_page_hierarchy(pages, options[:parent] ? page.parent_id : page.id)
212 212
      end
......
216 216
             "{{include(projectname:Foo)}} -- to include a page of a specific project wiki"
217 217
      macro :include do |obj, args|
218 218
        page = Wiki.find_page(args.first.to_s, :project => @project)
219
        raise 'Page not found' if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project)
219
        raise 'Page not found' if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project, global: page.wiki.global?)
220 220
        @included_wiki_pages ||= []
221 221
        raise 'Circular inclusion detected' if @included_wiki_pages.include?(page.id)
222 222
        @included_wiki_pages << page.id
(1-1/2)