New permission added: protect wiki pages. Once a page is protected, it can be edited/renamed/deleted only by users who have this permission. git-svn-id: http://redmine.rubyforge.org/svn/trunk@1415 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
556df99456
commit
0476669735
|
@ -21,7 +21,7 @@ class WikiController < ApplicationController
|
||||||
layout 'base'
|
layout 'base'
|
||||||
before_filter :find_wiki, :authorize
|
before_filter :find_wiki, :authorize
|
||||||
|
|
||||||
verify :method => :post, :only => [:destroy, :destroy_attachment], :redirect_to => { :action => :index }
|
verify :method => :post, :only => [:destroy, :destroy_attachment, :protect], :redirect_to => { :action => :index }
|
||||||
|
|
||||||
helper :attachments
|
helper :attachments
|
||||||
include AttachmentsHelper
|
include AttachmentsHelper
|
||||||
|
@ -48,12 +48,14 @@ class WikiController < ApplicationController
|
||||||
send_data(@content.text, :type => 'text/plain', :filename => "#{@page.title}.txt")
|
send_data(@content.text, :type => 'text/plain', :filename => "#{@page.title}.txt")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@editable = editable?
|
||||||
render :action => 'show'
|
render :action => 'show'
|
||||||
end
|
end
|
||||||
|
|
||||||
# edit an existing page or a new one
|
# edit an existing page or a new one
|
||||||
def edit
|
def edit
|
||||||
@page = @wiki.find_or_new_page(params[:page])
|
@page = @wiki.find_or_new_page(params[:page])
|
||||||
|
return render_403 unless editable?
|
||||||
@page.content = WikiContent.new(:page => @page) if @page.new_record?
|
@page.content = WikiContent.new(:page => @page) if @page.new_record?
|
||||||
|
|
||||||
@content = @page.content_for_version(params[:version])
|
@content = @page.content_for_version(params[:version])
|
||||||
|
@ -82,7 +84,8 @@ class WikiController < ApplicationController
|
||||||
|
|
||||||
# rename a page
|
# rename a page
|
||||||
def rename
|
def rename
|
||||||
@page = @wiki.find_page(params[:page])
|
@page = @wiki.find_page(params[:page])
|
||||||
|
return render_403 unless editable?
|
||||||
@page.redirect_existing_links = true
|
@page.redirect_existing_links = true
|
||||||
# used to display the *original* title if some AR validation errors occur
|
# used to display the *original* title if some AR validation errors occur
|
||||||
@original_title = @page.pretty_title
|
@original_title = @page.pretty_title
|
||||||
|
@ -92,6 +95,12 @@ class WikiController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def protect
|
||||||
|
page = @wiki.find_page(params[:page])
|
||||||
|
page.update_attribute :protected, params[:protected]
|
||||||
|
redirect_to :action => 'index', :id => @project, :page => page.title
|
||||||
|
end
|
||||||
|
|
||||||
# show page history
|
# show page history
|
||||||
def history
|
def history
|
||||||
@page = @wiki.find_page(params[:page])
|
@page = @wiki.find_page(params[:page])
|
||||||
|
@ -122,6 +131,7 @@ class WikiController < ApplicationController
|
||||||
# remove a wiki page and its history
|
# remove a wiki page and its history
|
||||||
def destroy
|
def destroy
|
||||||
@page = @wiki.find_page(params[:page])
|
@page = @wiki.find_page(params[:page])
|
||||||
|
return render_403 unless editable?
|
||||||
@page.destroy if @page
|
@page.destroy if @page
|
||||||
redirect_to :action => 'special', :id => @project, :page => 'Page_index'
|
redirect_to :action => 'special', :id => @project, :page => 'Page_index'
|
||||||
end
|
end
|
||||||
|
@ -152,6 +162,7 @@ class WikiController < ApplicationController
|
||||||
|
|
||||||
def preview
|
def preview
|
||||||
page = @wiki.find_page(params[:page])
|
page = @wiki.find_page(params[:page])
|
||||||
|
return render_403 unless editable?(page)
|
||||||
@attachements = page.attachments if page
|
@attachements = page.attachments if page
|
||||||
@text = params[:content][:text]
|
@text = params[:content][:text]
|
||||||
render :partial => 'common/preview'
|
render :partial => 'common/preview'
|
||||||
|
@ -159,12 +170,14 @@ class WikiController < ApplicationController
|
||||||
|
|
||||||
def add_attachment
|
def add_attachment
|
||||||
@page = @wiki.find_page(params[:page])
|
@page = @wiki.find_page(params[:page])
|
||||||
|
return render_403 unless editable?
|
||||||
attach_files(@page, params[:attachments])
|
attach_files(@page, params[:attachments])
|
||||||
redirect_to :action => 'index', :page => @page.title
|
redirect_to :action => 'index', :page => @page.title
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy_attachment
|
def destroy_attachment
|
||||||
@page = @wiki.find_page(params[:page])
|
@page = @wiki.find_page(params[:page])
|
||||||
|
return render_403 unless editable?
|
||||||
@page.attachments.find(params[:attachment_id]).destroy
|
@page.attachments.find(params[:attachment_id]).destroy
|
||||||
redirect_to :action => 'index', :page => @page.title
|
redirect_to :action => 'index', :page => @page.title
|
||||||
end
|
end
|
||||||
|
@ -178,4 +191,9 @@ private
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns true if the current user is allowed to edit the page, otherwise false
|
||||||
|
def editable?(page = @page)
|
||||||
|
page.editable_by?(User.current)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -105,6 +105,11 @@ class WikiPage < ActiveRecord::Base
|
||||||
def text
|
def text
|
||||||
content.text if content
|
content.text if content
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class WikiDiff
|
class WikiDiff
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
<div class="contextual">
|
<div class="contextual">
|
||||||
|
<% if @editable %>
|
||||||
<%= link_to_if_authorized(l(:button_edit), {:action => 'edit', :page => @page.title}, :class => 'icon icon-edit', :accesskey => accesskey(:edit)) if @content.version == @page.content.version %>
|
<%= link_to_if_authorized(l(:button_edit), {:action => 'edit', :page => @page.title}, :class => 'icon icon-edit', :accesskey => accesskey(:edit)) if @content.version == @page.content.version %>
|
||||||
|
<%= link_to_if_authorized(l(:button_lock), {:action => 'protect', :page => @page.title, :protected => 1}, :method => :post, :class => 'icon icon-lock') if !@page.protected? %>
|
||||||
|
<%= link_to_if_authorized(l(:button_unlock), {:action => 'protect', :page => @page.title, :protected => 0}, :method => :post, :class => 'icon icon-unlock') if @page.protected? %>
|
||||||
<%= link_to_if_authorized(l(:button_rename), {:action => 'rename', :page => @page.title}, :class => 'icon icon-move') if @content.version == @page.content.version %>
|
<%= link_to_if_authorized(l(:button_rename), {:action => 'rename', :page => @page.title}, :class => 'icon icon-move') if @content.version == @page.content.version %>
|
||||||
<%= link_to_if_authorized(l(:button_delete), {:action => 'destroy', :page => @page.title}, :method => :post, :confirm => l(:text_are_you_sure), :class => 'icon icon-del') %>
|
<%= link_to_if_authorized(l(:button_delete), {:action => 'destroy', :page => @page.title}, :method => :post, :confirm => l(:text_are_you_sure), :class => 'icon icon-del') %>
|
||||||
<%= link_to_if_authorized(l(:button_rollback), {:action => 'edit', :page => @page.title, :version => @content.version }, :class => 'icon icon-cancel') if @content.version < @page.content.version %>
|
<%= link_to_if_authorized(l(:button_rollback), {:action => 'edit', :page => @page.title, :version => @content.version }, :class => 'icon icon-cancel') if @content.version < @page.content.version %>
|
||||||
|
<% end %>
|
||||||
<%= link_to(l(:label_history), {:action => 'history', :page => @page.title}, :class => 'icon icon-history') %>
|
<%= link_to(l(:label_history), {:action => 'history', :page => @page.title}, :class => 'icon icon-history') %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -22,9 +26,9 @@
|
||||||
|
|
||||||
<%= render(:partial => "wiki/content", :locals => {:content => @content}) %>
|
<%= render(:partial => "wiki/content", :locals => {:content => @content}) %>
|
||||||
|
|
||||||
<%= link_to_attachments @page.attachments, :delete_url => (authorize_for('wiki', 'destroy_attachment') ? {:controller => 'wiki', :action => 'destroy_attachment', :page => @page.title} : nil) %>
|
<%= link_to_attachments @page.attachments, :delete_url => ((@editable && authorize_for('wiki', 'destroy_attachment')) ? {:controller => 'wiki', :action => 'destroy_attachment', :page => @page.title} : nil) %>
|
||||||
|
|
||||||
<% if authorize_for('wiki', 'add_attachment') %>
|
<% if @editable && authorize_for('wiki', 'add_attachment') %>
|
||||||
<p><%= link_to l(:label_attachment_new), {}, :onclick => "Element.show('add_attachment_form'); Element.hide(this); Element.scrollTo('add_attachment_form'); return false;",
|
<p><%= link_to l(:label_attachment_new), {}, :onclick => "Element.show('add_attachment_form'); Element.hide(this); Element.scrollTo('add_attachment_form'); return false;",
|
||||||
:id => 'attach_files_link' %></p>
|
:id => 'attach_files_link' %></p>
|
||||||
<% form_tag({ :controller => 'wiki', :action => 'add_attachment', :page => @page.title }, :multipart => true, :id => "add_attachment_form", :style => "display:none;") do %>
|
<% form_tag({ :controller => 'wiki', :action => 'add_attachment', :page => @page.title }, :multipart => true, :id => "add_attachment_form", :style => "display:none;") do %>
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
class AddWikiPagesProtected < ActiveRecord::Migration
|
||||||
|
def self.up
|
||||||
|
add_column :wiki_pages, :protected, :boolean, :default => false, :null => false
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.down
|
||||||
|
remove_column :wiki_pages, :protected
|
||||||
|
end
|
||||||
|
end
|
|
@ -76,6 +76,7 @@ Redmine::AccessControl.map do |map|
|
||||||
map.permission :delete_wiki_pages, {:wiki => :destroy}, :require => :member
|
map.permission :delete_wiki_pages, {:wiki => :destroy}, :require => :member
|
||||||
map.permission :view_wiki_pages, :wiki => [:index, :history, :diff, :annotate, :special]
|
map.permission :view_wiki_pages, :wiki => [:index, :history, :diff, :annotate, :special]
|
||||||
map.permission :edit_wiki_pages, :wiki => [:edit, :preview, :add_attachment, :destroy_attachment]
|
map.permission :edit_wiki_pages, :wiki => [:edit, :preview, :add_attachment, :destroy_attachment]
|
||||||
|
map.permission :protect_wiki_pages, {:wiki => :protect}, :require => :member
|
||||||
end
|
end
|
||||||
|
|
||||||
map.project_module :repository do |map|
|
map.project_module :repository do |map|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 566 B After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 643 B After Width: | Height: | Size: 618 B |
|
@ -29,6 +29,7 @@ roles_001:
|
||||||
- :manage_documents
|
- :manage_documents
|
||||||
- :view_wiki_pages
|
- :view_wiki_pages
|
||||||
- :edit_wiki_pages
|
- :edit_wiki_pages
|
||||||
|
- :protect_wiki_pages
|
||||||
- :delete_wiki_pages
|
- :delete_wiki_pages
|
||||||
- :rename_wiki_pages
|
- :rename_wiki_pages
|
||||||
- :add_messages
|
- :add_messages
|
||||||
|
@ -69,6 +70,7 @@ roles_002:
|
||||||
- :manage_documents
|
- :manage_documents
|
||||||
- :view_wiki_pages
|
- :view_wiki_pages
|
||||||
- :edit_wiki_pages
|
- :edit_wiki_pages
|
||||||
|
- :protect_wiki_pages
|
||||||
- :delete_wiki_pages
|
- :delete_wiki_pages
|
||||||
- :add_messages
|
- :add_messages
|
||||||
- :manage_boards
|
- :manage_boards
|
||||||
|
|
|
@ -4,19 +4,23 @@ wiki_pages_001:
|
||||||
title: CookBook_documentation
|
title: CookBook_documentation
|
||||||
id: 1
|
id: 1
|
||||||
wiki_id: 1
|
wiki_id: 1
|
||||||
|
protected: true
|
||||||
wiki_pages_002:
|
wiki_pages_002:
|
||||||
created_on: 2007-03-08 00:18:07 +01:00
|
created_on: 2007-03-08 00:18:07 +01:00
|
||||||
title: Another_page
|
title: Another_page
|
||||||
id: 2
|
id: 2
|
||||||
wiki_id: 1
|
wiki_id: 1
|
||||||
|
protected: false
|
||||||
wiki_pages_003:
|
wiki_pages_003:
|
||||||
created_on: 2007-03-08 00:18:07 +01:00
|
created_on: 2007-03-08 00:18:07 +01:00
|
||||||
title: Start_page
|
title: Start_page
|
||||||
id: 3
|
id: 3
|
||||||
wiki_id: 2
|
wiki_id: 2
|
||||||
|
protected: false
|
||||||
wiki_pages_004:
|
wiki_pages_004:
|
||||||
created_on: 2007-03-08 00:18:07 +01:00
|
created_on: 2007-03-08 00:18:07 +01:00
|
||||||
title: Page_with_an_inline_image
|
title: Page_with_an_inline_image
|
||||||
id: 4
|
id: 4
|
||||||
wiki_id: 1
|
wiki_id: 1
|
||||||
|
protected: false
|
||||||
|
|
|
@ -160,4 +160,60 @@ class WikiControllerTest < Test::Unit::TestCase
|
||||||
get :index, :id => 999
|
get :index, :id => 999
|
||||||
assert_response 404
|
assert_response 404
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_protect_page
|
||||||
|
page = WikiPage.find_by_wiki_id_and_title(1, 'Another_page')
|
||||||
|
assert !page.protected?
|
||||||
|
@request.session[:user_id] = 2
|
||||||
|
post :protect, :id => 1, :page => page.title, :protected => '1'
|
||||||
|
assert_redirected_to 'wiki/ecookbook/Another_page'
|
||||||
|
assert page.reload.protected?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_unprotect_page
|
||||||
|
page = WikiPage.find_by_wiki_id_and_title(1, 'CookBook_documentation')
|
||||||
|
assert page.protected?
|
||||||
|
@request.session[:user_id] = 2
|
||||||
|
post :protect, :id => 1, :page => page.title, :protected => '0'
|
||||||
|
assert_redirected_to 'wiki/ecookbook'
|
||||||
|
assert !page.reload.protected?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_show_page_with_edit_link
|
||||||
|
@request.session[:user_id] = 2
|
||||||
|
get :index, :id => 1
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'show'
|
||||||
|
assert_tag :tag => 'a', :attributes => { :href => '/wiki/1/CookBook_documentation/edit' }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_show_page_without_edit_link
|
||||||
|
@request.session[:user_id] = 4
|
||||||
|
get :index, :id => 1
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'show'
|
||||||
|
assert_no_tag :tag => 'a', :attributes => { :href => '/wiki/1/CookBook_documentation/edit' }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_edit_unprotected_page
|
||||||
|
# Non members can edit unprotected wiki pages
|
||||||
|
@request.session[:user_id] = 4
|
||||||
|
get :edit, :id => 1, :page => 'Another_page'
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'edit'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_edit_protected_page_by_nonmember
|
||||||
|
# Non members can't edit protected wiki pages
|
||||||
|
@request.session[:user_id] = 4
|
||||||
|
get :edit, :id => 1, :page => 'CookBook_documentation'
|
||||||
|
assert_response 403
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_edit_protected_page_by_member
|
||||||
|
@request.session[:user_id] = 2
|
||||||
|
get :edit, :id => 1, :page => 'CookBook_documentation'
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'edit'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue