Revision 1415
Added by Jean-Philippe Lang about 17 years ago
trunk/app/controllers/wiki_controller.rb | ||
---|---|---|
21 | 21 |
layout 'base' |
22 | 22 |
before_filter :find_wiki, :authorize |
23 | 23 |
|
24 |
verify :method => :post, :only => [:destroy, :destroy_attachment], :redirect_to => { :action => :index } |
|
24 |
verify :method => :post, :only => [:destroy, :destroy_attachment, :protect], :redirect_to => { :action => :index }
|
|
25 | 25 |
|
26 | 26 |
helper :attachments |
27 | 27 |
include AttachmentsHelper |
... | ... | |
48 | 48 |
send_data(@content.text, :type => 'text/plain', :filename => "#{@page.title}.txt") |
49 | 49 |
return |
50 | 50 |
end |
51 |
@editable = editable? |
|
51 | 52 |
render :action => 'show' |
52 | 53 |
end |
53 | 54 |
|
54 | 55 |
# edit an existing page or a new one |
55 | 56 |
def edit |
56 | 57 |
@page = @wiki.find_or_new_page(params[:page]) |
58 |
return render_403 unless editable? |
|
57 | 59 |
@page.content = WikiContent.new(:page => @page) if @page.new_record? |
58 | 60 |
|
59 | 61 |
@content = @page.content_for_version(params[:version]) |
... | ... | |
82 | 84 |
|
83 | 85 |
# rename a page |
84 | 86 |
def rename |
85 |
@page = @wiki.find_page(params[:page]) |
|
87 |
@page = @wiki.find_page(params[:page]) |
|
88 |
return render_403 unless editable? |
|
86 | 89 |
@page.redirect_existing_links = true |
87 | 90 |
# used to display the *original* title if some AR validation errors occur |
88 | 91 |
@original_title = @page.pretty_title |
... | ... | |
92 | 95 |
end |
93 | 96 |
end |
94 | 97 |
|
98 |
def protect |
|
99 |
page = @wiki.find_page(params[:page]) |
|
100 |
page.update_attribute :protected, params[:protected] |
|
101 |
redirect_to :action => 'index', :id => @project, :page => page.title |
|
102 |
end |
|
103 |
|
|
95 | 104 |
# show page history |
96 | 105 |
def history |
97 | 106 |
@page = @wiki.find_page(params[:page]) |
... | ... | |
122 | 131 |
# remove a wiki page and its history |
123 | 132 |
def destroy |
124 | 133 |
@page = @wiki.find_page(params[:page]) |
134 |
return render_403 unless editable? |
|
125 | 135 |
@page.destroy if @page |
126 | 136 |
redirect_to :action => 'special', :id => @project, :page => 'Page_index' |
127 | 137 |
end |
... | ... | |
152 | 162 |
|
153 | 163 |
def preview |
154 | 164 |
page = @wiki.find_page(params[:page]) |
165 |
return render_403 unless editable?(page) |
|
155 | 166 |
@attachements = page.attachments if page |
156 | 167 |
@text = params[:content][:text] |
157 | 168 |
render :partial => 'common/preview' |
... | ... | |
159 | 170 |
|
160 | 171 |
def add_attachment |
161 | 172 |
@page = @wiki.find_page(params[:page]) |
173 |
return render_403 unless editable? |
|
162 | 174 |
attach_files(@page, params[:attachments]) |
163 | 175 |
redirect_to :action => 'index', :page => @page.title |
164 | 176 |
end |
165 | 177 |
|
166 | 178 |
def destroy_attachment |
167 | 179 |
@page = @wiki.find_page(params[:page]) |
180 |
return render_403 unless editable? |
|
168 | 181 |
@page.attachments.find(params[:attachment_id]).destroy |
169 | 182 |
redirect_to :action => 'index', :page => @page.title |
170 | 183 |
end |
... | ... | |
178 | 191 |
rescue ActiveRecord::RecordNotFound |
179 | 192 |
render_404 |
180 | 193 |
end |
194 |
|
|
195 |
# Returns true if the current user is allowed to edit the page, otherwise false |
|
196 |
def editable?(page = @page) |
|
197 |
page.editable_by?(User.current) |
|
198 |
end |
|
181 | 199 |
end |
trunk/app/models/wiki_page.rb | ||
---|---|---|
105 | 105 |
def text |
106 | 106 |
content.text if content |
107 | 107 |
end |
108 |
|
|
109 |
# Returns true if usr is allowed to edit the page, otherwise false |
|
110 |
def editable_by?(usr) |
|
111 |
!protected? || usr.allowed_to?(:protect_wiki_pages, wiki.project) |
|
112 |
end |
|
108 | 113 |
end |
109 | 114 |
|
110 | 115 |
class WikiDiff |
trunk/app/views/wiki/show.rhtml | ||
---|---|---|
1 | 1 |
<div class="contextual"> |
2 |
<% if @editable %> |
|
2 | 3 |
<%= 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 %> |
4 |
<%= link_to_if_authorized(l(:button_lock), {:action => 'protect', :page => @page.title, :protected => 1}, :method => :post, :class => 'icon icon-lock') if [email protected]? %> |
|
5 |
<%= link_to_if_authorized(l(:button_unlock), {:action => 'protect', :page => @page.title, :protected => 0}, :method => :post, :class => 'icon icon-unlock') if @page.protected? %> |
|
3 | 6 |
<%= link_to_if_authorized(l(:button_rename), {:action => 'rename', :page => @page.title}, :class => 'icon icon-move') if @content.version == @page.content.version %> |
4 | 7 |
<%= link_to_if_authorized(l(:button_delete), {:action => 'destroy', :page => @page.title}, :method => :post, :confirm => l(:text_are_you_sure), :class => 'icon icon-del') %> |
5 | 8 |
<%= 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 %> |
9 |
<% end %> |
|
6 | 10 |
<%= link_to(l(:label_history), {:action => 'history', :page => @page.title}, :class => 'icon icon-history') %> |
7 | 11 |
</div> |
8 | 12 |
|
... | ... | |
22 | 26 |
|
23 | 27 |
<%= render(:partial => "wiki/content", :locals => {:content => @content}) %> |
24 | 28 |
|
25 |
<%= link_to_attachments @page.attachments, :delete_url => (authorize_for('wiki', 'destroy_attachment') ? {:controller => 'wiki', :action => 'destroy_attachment', :page => @page.title} : nil) %>
|
|
29 |
<%= link_to_attachments @page.attachments, :delete_url => ((@editable && authorize_for('wiki', 'destroy_attachment')) ? {:controller => 'wiki', :action => 'destroy_attachment', :page => @page.title} : nil) %>
|
|
26 | 30 |
|
27 |
<% if authorize_for('wiki', 'add_attachment') %> |
|
31 |
<% if @editable && authorize_for('wiki', 'add_attachment') %>
|
|
28 | 32 |
<p><%= link_to l(:label_attachment_new), {}, :onclick => "Element.show('add_attachment_form'); Element.hide(this); Element.scrollTo('add_attachment_form'); return false;", |
29 | 33 |
:id => 'attach_files_link' %></p> |
30 | 34 |
<% form_tag({ :controller => 'wiki', :action => 'add_attachment', :page => @page.title }, :multipart => true, :id => "add_attachment_form", :style => "display:none;") do %> |
trunk/db/migrate/093_add_wiki_pages_protected.rb | ||
---|---|---|
1 |
class AddWikiPagesProtected < ActiveRecord::Migration |
|
2 |
def self.up |
|
3 |
add_column :wiki_pages, :protected, :boolean, :default => false, :null => false |
|
4 |
end |
|
5 |
|
|
6 |
def self.down |
|
7 |
remove_column :wiki_pages, :protected |
|
8 |
end |
|
9 |
end |
|
0 | 10 |
trunk/lib/redmine.rb | ||
---|---|---|
76 | 76 |
map.permission :delete_wiki_pages, {:wiki => :destroy}, :require => :member |
77 | 77 |
map.permission :view_wiki_pages, :wiki => [:index, :history, :diff, :annotate, :special] |
78 | 78 |
map.permission :edit_wiki_pages, :wiki => [:edit, :preview, :add_attachment, :destroy_attachment] |
79 |
map.permission :protect_wiki_pages, {:wiki => :protect}, :require => :member |
|
79 | 80 |
end |
80 | 81 |
|
81 | 82 |
map.project_module :repository do |map| |
trunk/test/fixtures/roles.yml | ||
---|---|---|
29 | 29 |
- :manage_documents |
30 | 30 |
- :view_wiki_pages |
31 | 31 |
- :edit_wiki_pages |
32 |
- :protect_wiki_pages |
|
32 | 33 |
- :delete_wiki_pages |
33 | 34 |
- :rename_wiki_pages |
34 | 35 |
- :add_messages |
... | ... | |
69 | 70 |
- :manage_documents |
70 | 71 |
- :view_wiki_pages |
71 | 72 |
- :edit_wiki_pages |
73 |
- :protect_wiki_pages |
|
72 | 74 |
- :delete_wiki_pages |
73 | 75 |
- :add_messages |
74 | 76 |
- :manage_boards |
trunk/test/fixtures/wiki_pages.yml | ||
---|---|---|
4 | 4 |
title: CookBook_documentation |
5 | 5 |
id: 1 |
6 | 6 |
wiki_id: 1 |
7 |
protected: true |
|
7 | 8 |
wiki_pages_002: |
8 | 9 |
created_on: 2007-03-08 00:18:07 +01:00 |
9 | 10 |
title: Another_page |
10 | 11 |
id: 2 |
11 | 12 |
wiki_id: 1 |
13 |
protected: false |
|
12 | 14 |
wiki_pages_003: |
13 | 15 |
created_on: 2007-03-08 00:18:07 +01:00 |
14 | 16 |
title: Start_page |
15 | 17 |
id: 3 |
16 | 18 |
wiki_id: 2 |
19 |
protected: false |
|
17 | 20 |
wiki_pages_004: |
18 | 21 |
created_on: 2007-03-08 00:18:07 +01:00 |
19 | 22 |
title: Page_with_an_inline_image |
20 | 23 |
id: 4 |
21 | 24 |
wiki_id: 1 |
25 |
protected: false |
|
22 | 26 |
|
trunk/test/functional/wiki_controller_test.rb | ||
---|---|---|
160 | 160 |
get :index, :id => 999 |
161 | 161 |
assert_response 404 |
162 | 162 |
end |
163 |
|
|
164 |
def test_protect_page |
|
165 |
page = WikiPage.find_by_wiki_id_and_title(1, 'Another_page') |
|
166 |
assert !page.protected? |
|
167 |
@request.session[:user_id] = 2 |
|
168 |
post :protect, :id => 1, :page => page.title, :protected => '1' |
|
169 |
assert_redirected_to 'wiki/ecookbook/Another_page' |
|
170 |
assert page.reload.protected? |
|
171 |
end |
|
172 |
|
|
173 |
def test_unprotect_page |
|
174 |
page = WikiPage.find_by_wiki_id_and_title(1, 'CookBook_documentation') |
|
175 |
assert page.protected? |
|
176 |
@request.session[:user_id] = 2 |
|
177 |
post :protect, :id => 1, :page => page.title, :protected => '0' |
|
178 |
assert_redirected_to 'wiki/ecookbook' |
|
179 |
assert !page.reload.protected? |
|
180 |
end |
|
181 |
|
|
182 |
def test_show_page_with_edit_link |
|
183 |
@request.session[:user_id] = 2 |
|
184 |
get :index, :id => 1 |
|
185 |
assert_response :success |
|
186 |
assert_template 'show' |
|
187 |
assert_tag :tag => 'a', :attributes => { :href => '/wiki/1/CookBook_documentation/edit' } |
|
188 |
end |
|
189 |
|
|
190 |
def test_show_page_without_edit_link |
|
191 |
@request.session[:user_id] = 4 |
|
192 |
get :index, :id => 1 |
|
193 |
assert_response :success |
|
194 |
assert_template 'show' |
|
195 |
assert_no_tag :tag => 'a', :attributes => { :href => '/wiki/1/CookBook_documentation/edit' } |
|
196 |
end |
|
197 |
|
|
198 |
def test_edit_unprotected_page |
|
199 |
# Non members can edit unprotected wiki pages |
|
200 |
@request.session[:user_id] = 4 |
|
201 |
get :edit, :id => 1, :page => 'Another_page' |
|
202 |
assert_response :success |
|
203 |
assert_template 'edit' |
|
204 |
end |
|
205 |
|
|
206 |
def test_edit_protected_page_by_nonmember |
|
207 |
# Non members can't edit protected wiki pages |
|
208 |
@request.session[:user_id] = 4 |
|
209 |
get :edit, :id => 1, :page => 'CookBook_documentation' |
|
210 |
assert_response 403 |
|
211 |
end |
|
212 |
|
|
213 |
def test_edit_protected_page_by_member |
|
214 |
@request.session[:user_id] = 2 |
|
215 |
get :edit, :id => 1, :page => 'CookBook_documentation' |
|
216 |
assert_response :success |
|
217 |
assert_template 'edit' |
|
218 |
end |
|
163 | 219 |
end |
Also available in: Unified diff
Wiki page protection (#851, patch #1146 by Mateo Murphy with slight changes).
New permission added: protect wiki pages. Once a page is protected, it can be edited/renamed/deleted only by users who have this permission.