##// END OF EJS Templates
Adds a permission 'view wiki edits' so that wiki history can be hidden to certain users (#1154)....
Jean-Philippe Lang -
r1813:455abea32042
parent child
Show More
@@ -0,0 +1,13
1 class AddWiewWikiEditsPermission < ActiveRecord::Migration
2 def self.up
3 Role.find(:all).each do |r|
4 r.add_permission!(:view_wiki_edits) if r.has_permission?(:view_wiki_pages)
5 end
6 end
7
8 def self.down
9 Role.find(:all).each do |r|
10 r.remove_permission!(:view_wiki_edits)
11 end
12 end
13 end
@@ -1,203 +1,208
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require 'diff'
18 require 'diff'
19
19
20 class WikiController < ApplicationController
20 class WikiController < ApplicationController
21 before_filter :find_wiki, :authorize
21 before_filter :find_wiki, :authorize
22
22
23 verify :method => :post, :only => [:destroy, :destroy_attachment, :protect], :redirect_to => { :action => :index }
23 verify :method => :post, :only => [:destroy, :destroy_attachment, :protect], :redirect_to => { :action => :index }
24
24
25 helper :attachments
25 helper :attachments
26 include AttachmentsHelper
26 include AttachmentsHelper
27
27
28 # display a page (in editing mode if it doesn't exist)
28 # display a page (in editing mode if it doesn't exist)
29 def index
29 def index
30 page_title = params[:page]
30 page_title = params[:page]
31 @page = @wiki.find_or_new_page(page_title)
31 @page = @wiki.find_or_new_page(page_title)
32 if @page.new_record?
32 if @page.new_record?
33 if User.current.allowed_to?(:edit_wiki_pages, @project)
33 if User.current.allowed_to?(:edit_wiki_pages, @project)
34 edit
34 edit
35 render :action => 'edit'
35 render :action => 'edit'
36 else
36 else
37 render_404
37 render_404
38 end
38 end
39 return
39 return
40 end
40 end
41 if params[:version] && !User.current.allowed_to?(:view_wiki_edits, @project)
42 # Redirects user to the current version if he's not allowed to view previous versions
43 redirect_to :version => nil
44 return
45 end
41 @content = @page.content_for_version(params[:version])
46 @content = @page.content_for_version(params[:version])
42 if params[:export] == 'html'
47 if params[:export] == 'html'
43 export = render_to_string :action => 'export', :layout => false
48 export = render_to_string :action => 'export', :layout => false
44 send_data(export, :type => 'text/html', :filename => "#{@page.title}.html")
49 send_data(export, :type => 'text/html', :filename => "#{@page.title}.html")
45 return
50 return
46 elsif params[:export] == 'txt'
51 elsif params[:export] == 'txt'
47 send_data(@content.text, :type => 'text/plain', :filename => "#{@page.title}.txt")
52 send_data(@content.text, :type => 'text/plain', :filename => "#{@page.title}.txt")
48 return
53 return
49 end
54 end
50 @editable = editable?
55 @editable = editable?
51 render :action => 'show'
56 render :action => 'show'
52 end
57 end
53
58
54 # edit an existing page or a new one
59 # edit an existing page or a new one
55 def edit
60 def edit
56 @page = @wiki.find_or_new_page(params[:page])
61 @page = @wiki.find_or_new_page(params[:page])
57 return render_403 unless editable?
62 return render_403 unless editable?
58 @page.content = WikiContent.new(:page => @page) if @page.new_record?
63 @page.content = WikiContent.new(:page => @page) if @page.new_record?
59
64
60 @content = @page.content_for_version(params[:version])
65 @content = @page.content_for_version(params[:version])
61 @content.text = "h1. #{@page.pretty_title}" if @content.text.blank?
66 @content.text = "h1. #{@page.pretty_title}" if @content.text.blank?
62 # don't keep previous comment
67 # don't keep previous comment
63 @content.comments = nil
68 @content.comments = nil
64 if request.post?
69 if request.post?
65 if !@page.new_record? && @content.text == params[:content][:text]
70 if !@page.new_record? && @content.text == params[:content][:text]
66 # don't save if text wasn't changed
71 # don't save if text wasn't changed
67 redirect_to :action => 'index', :id => @project, :page => @page.title
72 redirect_to :action => 'index', :id => @project, :page => @page.title
68 return
73 return
69 end
74 end
70 #@content.text = params[:content][:text]
75 #@content.text = params[:content][:text]
71 #@content.comments = params[:content][:comments]
76 #@content.comments = params[:content][:comments]
72 @content.attributes = params[:content]
77 @content.attributes = params[:content]
73 @content.author = User.current
78 @content.author = User.current
74 # if page is new @page.save will also save content, but not if page isn't a new record
79 # if page is new @page.save will also save content, but not if page isn't a new record
75 if (@page.new_record? ? @page.save : @content.save)
80 if (@page.new_record? ? @page.save : @content.save)
76 redirect_to :action => 'index', :id => @project, :page => @page.title
81 redirect_to :action => 'index', :id => @project, :page => @page.title
77 end
82 end
78 end
83 end
79 rescue ActiveRecord::StaleObjectError
84 rescue ActiveRecord::StaleObjectError
80 # Optimistic locking exception
85 # Optimistic locking exception
81 flash[:error] = l(:notice_locking_conflict)
86 flash[:error] = l(:notice_locking_conflict)
82 end
87 end
83
88
84 # rename a page
89 # rename a page
85 def rename
90 def rename
86 @page = @wiki.find_page(params[:page])
91 @page = @wiki.find_page(params[:page])
87 return render_403 unless editable?
92 return render_403 unless editable?
88 @page.redirect_existing_links = true
93 @page.redirect_existing_links = true
89 # used to display the *original* title if some AR validation errors occur
94 # used to display the *original* title if some AR validation errors occur
90 @original_title = @page.pretty_title
95 @original_title = @page.pretty_title
91 if request.post? && @page.update_attributes(params[:wiki_page])
96 if request.post? && @page.update_attributes(params[:wiki_page])
92 flash[:notice] = l(:notice_successful_update)
97 flash[:notice] = l(:notice_successful_update)
93 redirect_to :action => 'index', :id => @project, :page => @page.title
98 redirect_to :action => 'index', :id => @project, :page => @page.title
94 end
99 end
95 end
100 end
96
101
97 def protect
102 def protect
98 page = @wiki.find_page(params[:page])
103 page = @wiki.find_page(params[:page])
99 page.update_attribute :protected, params[:protected]
104 page.update_attribute :protected, params[:protected]
100 redirect_to :action => 'index', :id => @project, :page => page.title
105 redirect_to :action => 'index', :id => @project, :page => page.title
101 end
106 end
102
107
103 # show page history
108 # show page history
104 def history
109 def history
105 @page = @wiki.find_page(params[:page])
110 @page = @wiki.find_page(params[:page])
106
111
107 @version_count = @page.content.versions.count
112 @version_count = @page.content.versions.count
108 @version_pages = Paginator.new self, @version_count, per_page_option, params['p']
113 @version_pages = Paginator.new self, @version_count, per_page_option, params['p']
109 # don't load text
114 # don't load text
110 @versions = @page.content.versions.find :all,
115 @versions = @page.content.versions.find :all,
111 :select => "id, author_id, comments, updated_on, version",
116 :select => "id, author_id, comments, updated_on, version",
112 :order => 'version DESC',
117 :order => 'version DESC',
113 :limit => @version_pages.items_per_page + 1,
118 :limit => @version_pages.items_per_page + 1,
114 :offset => @version_pages.current.offset
119 :offset => @version_pages.current.offset
115
120
116 render :layout => false if request.xhr?
121 render :layout => false if request.xhr?
117 end
122 end
118
123
119 def diff
124 def diff
120 @page = @wiki.find_page(params[:page])
125 @page = @wiki.find_page(params[:page])
121 @diff = @page.diff(params[:version], params[:version_from])
126 @diff = @page.diff(params[:version], params[:version_from])
122 render_404 unless @diff
127 render_404 unless @diff
123 end
128 end
124
129
125 def annotate
130 def annotate
126 @page = @wiki.find_page(params[:page])
131 @page = @wiki.find_page(params[:page])
127 @annotate = @page.annotate(params[:version])
132 @annotate = @page.annotate(params[:version])
128 end
133 end
129
134
130 # remove a wiki page and its history
135 # remove a wiki page and its history
131 def destroy
136 def destroy
132 @page = @wiki.find_page(params[:page])
137 @page = @wiki.find_page(params[:page])
133 return render_403 unless editable?
138 return render_403 unless editable?
134 @page.destroy if @page
139 @page.destroy if @page
135 redirect_to :action => 'special', :id => @project, :page => 'Page_index'
140 redirect_to :action => 'special', :id => @project, :page => 'Page_index'
136 end
141 end
137
142
138 # display special pages
143 # display special pages
139 def special
144 def special
140 page_title = params[:page].downcase
145 page_title = params[:page].downcase
141 case page_title
146 case page_title
142 # show pages index, sorted by title
147 # show pages index, sorted by title
143 when 'page_index', 'date_index'
148 when 'page_index', 'date_index'
144 # eager load information about last updates, without loading text
149 # eager load information about last updates, without loading text
145 @pages = @wiki.pages.find :all, :select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on",
150 @pages = @wiki.pages.find :all, :select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on",
146 :joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id",
151 :joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id",
147 :order => 'title'
152 :order => 'title'
148 @pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
153 @pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
149 @pages_by_parent_id = @pages.group_by(&:parent_id)
154 @pages_by_parent_id = @pages.group_by(&:parent_id)
150 # export wiki to a single html file
155 # export wiki to a single html file
151 when 'export'
156 when 'export'
152 @pages = @wiki.pages.find :all, :order => 'title'
157 @pages = @wiki.pages.find :all, :order => 'title'
153 export = render_to_string :action => 'export_multiple', :layout => false
158 export = render_to_string :action => 'export_multiple', :layout => false
154 send_data(export, :type => 'text/html', :filename => "wiki.html")
159 send_data(export, :type => 'text/html', :filename => "wiki.html")
155 return
160 return
156 else
161 else
157 # requested special page doesn't exist, redirect to default page
162 # requested special page doesn't exist, redirect to default page
158 redirect_to :action => 'index', :id => @project, :page => nil and return
163 redirect_to :action => 'index', :id => @project, :page => nil and return
159 end
164 end
160 render :action => "special_#{page_title}"
165 render :action => "special_#{page_title}"
161 end
166 end
162
167
163 def preview
168 def preview
164 page = @wiki.find_page(params[:page])
169 page = @wiki.find_page(params[:page])
165 # page is nil when previewing a new page
170 # page is nil when previewing a new page
166 return render_403 unless page.nil? || editable?(page)
171 return render_403 unless page.nil? || editable?(page)
167 if page
172 if page
168 @attachements = page.attachments
173 @attachements = page.attachments
169 @previewed = page.content
174 @previewed = page.content
170 end
175 end
171 @text = params[:content][:text]
176 @text = params[:content][:text]
172 render :partial => 'common/preview'
177 render :partial => 'common/preview'
173 end
178 end
174
179
175 def add_attachment
180 def add_attachment
176 @page = @wiki.find_page(params[:page])
181 @page = @wiki.find_page(params[:page])
177 return render_403 unless editable?
182 return render_403 unless editable?
178 attach_files(@page, params[:attachments])
183 attach_files(@page, params[:attachments])
179 redirect_to :action => 'index', :page => @page.title
184 redirect_to :action => 'index', :page => @page.title
180 end
185 end
181
186
182 def destroy_attachment
187 def destroy_attachment
183 @page = @wiki.find_page(params[:page])
188 @page = @wiki.find_page(params[:page])
184 return render_403 unless editable?
189 return render_403 unless editable?
185 @page.attachments.find(params[:attachment_id]).destroy
190 @page.attachments.find(params[:attachment_id]).destroy
186 redirect_to :action => 'index', :page => @page.title
191 redirect_to :action => 'index', :page => @page.title
187 end
192 end
188
193
189 private
194 private
190
195
191 def find_wiki
196 def find_wiki
192 @project = Project.find(params[:id])
197 @project = Project.find(params[:id])
193 @wiki = @project.wiki
198 @wiki = @project.wiki
194 render_404 unless @wiki
199 render_404 unless @wiki
195 rescue ActiveRecord::RecordNotFound
200 rescue ActiveRecord::RecordNotFound
196 render_404
201 render_404
197 end
202 end
198
203
199 # Returns true if the current user is allowed to edit the page, otherwise false
204 # Returns true if the current user is allowed to edit the page, otherwise false
200 def editable?(page = @page)
205 def editable?(page = @page)
201 page.editable_by?(User.current)
206 page.editable_by?(User.current)
202 end
207 end
203 end
208 end
@@ -1,142 +1,147
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006 Jean-Philippe Lang
2 # Copyright (C) 2006 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class Role < ActiveRecord::Base
18 class Role < ActiveRecord::Base
19 # Built-in roles
19 # Built-in roles
20 BUILTIN_NON_MEMBER = 1
20 BUILTIN_NON_MEMBER = 1
21 BUILTIN_ANONYMOUS = 2
21 BUILTIN_ANONYMOUS = 2
22
22
23 named_scope :builtin, lambda { |*args|
23 named_scope :builtin, lambda { |*args|
24 compare = 'not' if args.first == true
24 compare = 'not' if args.first == true
25 { :conditions => "#{compare} builtin = 0" }
25 { :conditions => "#{compare} builtin = 0" }
26 }
26 }
27
27
28 before_destroy :check_deletable
28 before_destroy :check_deletable
29 has_many :workflows, :dependent => :delete_all do
29 has_many :workflows, :dependent => :delete_all do
30 def copy(role)
30 def copy(role)
31 raise "Can not copy workflow from a #{role.class}" unless role.is_a?(Role)
31 raise "Can not copy workflow from a #{role.class}" unless role.is_a?(Role)
32 raise "Can not copy workflow from/to an unsaved role" if proxy_owner.new_record? || role.new_record?
32 raise "Can not copy workflow from/to an unsaved role" if proxy_owner.new_record? || role.new_record?
33 clear
33 clear
34 connection.insert "INSERT INTO workflows (tracker_id, old_status_id, new_status_id, role_id)" +
34 connection.insert "INSERT INTO workflows (tracker_id, old_status_id, new_status_id, role_id)" +
35 " SELECT tracker_id, old_status_id, new_status_id, #{proxy_owner.id}" +
35 " SELECT tracker_id, old_status_id, new_status_id, #{proxy_owner.id}" +
36 " FROM workflows" +
36 " FROM workflows" +
37 " WHERE role_id = #{role.id}"
37 " WHERE role_id = #{role.id}"
38 end
38 end
39 end
39 end
40
40
41 has_many :members
41 has_many :members
42 acts_as_list
42 acts_as_list
43
43
44 serialize :permissions, Array
44 serialize :permissions, Array
45 attr_protected :builtin
45 attr_protected :builtin
46
46
47 validates_presence_of :name
47 validates_presence_of :name
48 validates_uniqueness_of :name
48 validates_uniqueness_of :name
49 validates_length_of :name, :maximum => 30
49 validates_length_of :name, :maximum => 30
50 validates_format_of :name, :with => /^[\w\s\'\-]*$/i
50 validates_format_of :name, :with => /^[\w\s\'\-]*$/i
51
51
52 def permissions
52 def permissions
53 read_attribute(:permissions) || []
53 read_attribute(:permissions) || []
54 end
54 end
55
55
56 def permissions=(perms)
56 def permissions=(perms)
57 perms = perms.collect {|p| p.to_sym unless p.blank? }.compact.uniq if perms
57 perms = perms.collect {|p| p.to_sym unless p.blank? }.compact.uniq if perms
58 write_attribute(:permissions, perms)
58 write_attribute(:permissions, perms)
59 end
59 end
60
60
61 def add_permission!(*perms)
61 def add_permission!(*perms)
62 self.permissions = [] unless permissions.is_a?(Array)
62 self.permissions = [] unless permissions.is_a?(Array)
63
63
64 permissions_will_change!
64 permissions_will_change!
65 perms.each do |p|
65 perms.each do |p|
66 p = p.to_sym
66 p = p.to_sym
67 permissions << p unless permissions.include?(p)
67 permissions << p unless permissions.include?(p)
68 end
68 end
69 save!
69 save!
70 end
70 end
71
71
72 def remove_permission!(*perms)
72 def remove_permission!(*perms)
73 return unless permissions.is_a?(Array)
73 return unless permissions.is_a?(Array)
74 permissions_will_change!
74 permissions_will_change!
75 perms.each { |p| permissions.delete(p.to_sym) }
75 perms.each { |p| permissions.delete(p.to_sym) }
76 save!
76 save!
77 end
77 end
78
78
79 # Returns true if the role has the given permission
80 def has_permission?(perm)
81 !permissions.nil? && permissions.include?(perm.to_sym)
82 end
83
79 def <=>(role)
84 def <=>(role)
80 position <=> role.position
85 position <=> role.position
81 end
86 end
82
87
83 # Return true if the role is a builtin role
88 # Return true if the role is a builtin role
84 def builtin?
89 def builtin?
85 self.builtin != 0
90 self.builtin != 0
86 end
91 end
87
92
88 # Return true if the role is a project member role
93 # Return true if the role is a project member role
89 def member?
94 def member?
90 !self.builtin?
95 !self.builtin?
91 end
96 end
92
97
93 # Return true if role is allowed to do the specified action
98 # Return true if role is allowed to do the specified action
94 # action can be:
99 # action can be:
95 # * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit')
100 # * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit')
96 # * a permission Symbol (eg. :edit_project)
101 # * a permission Symbol (eg. :edit_project)
97 def allowed_to?(action)
102 def allowed_to?(action)
98 if action.is_a? Hash
103 if action.is_a? Hash
99 allowed_actions.include? "#{action[:controller]}/#{action[:action]}"
104 allowed_actions.include? "#{action[:controller]}/#{action[:action]}"
100 else
105 else
101 allowed_permissions.include? action
106 allowed_permissions.include? action
102 end
107 end
103 end
108 end
104
109
105 # Return all the permissions that can be given to the role
110 # Return all the permissions that can be given to the role
106 def setable_permissions
111 def setable_permissions
107 setable_permissions = Redmine::AccessControl.permissions - Redmine::AccessControl.public_permissions
112 setable_permissions = Redmine::AccessControl.permissions - Redmine::AccessControl.public_permissions
108 setable_permissions -= Redmine::AccessControl.members_only_permissions if self.builtin == BUILTIN_NON_MEMBER
113 setable_permissions -= Redmine::AccessControl.members_only_permissions if self.builtin == BUILTIN_NON_MEMBER
109 setable_permissions -= Redmine::AccessControl.loggedin_only_permissions if self.builtin == BUILTIN_ANONYMOUS
114 setable_permissions -= Redmine::AccessControl.loggedin_only_permissions if self.builtin == BUILTIN_ANONYMOUS
110 setable_permissions
115 setable_permissions
111 end
116 end
112
117
113 # Find all the roles that can be given to a project member
118 # Find all the roles that can be given to a project member
114 def self.find_all_givable
119 def self.find_all_givable
115 find(:all, :conditions => {:builtin => 0}, :order => 'position')
120 find(:all, :conditions => {:builtin => 0}, :order => 'position')
116 end
121 end
117
122
118 # Return the builtin 'non member' role
123 # Return the builtin 'non member' role
119 def self.non_member
124 def self.non_member
120 find(:first, :conditions => {:builtin => BUILTIN_NON_MEMBER}) || raise('Missing non-member builtin role.')
125 find(:first, :conditions => {:builtin => BUILTIN_NON_MEMBER}) || raise('Missing non-member builtin role.')
121 end
126 end
122
127
123 # Return the builtin 'anonymous' role
128 # Return the builtin 'anonymous' role
124 def self.anonymous
129 def self.anonymous
125 find(:first, :conditions => {:builtin => BUILTIN_ANONYMOUS}) || raise('Missing anonymous builtin role.')
130 find(:first, :conditions => {:builtin => BUILTIN_ANONYMOUS}) || raise('Missing anonymous builtin role.')
126 end
131 end
127
132
128
133
129 private
134 private
130 def allowed_permissions
135 def allowed_permissions
131 @allowed_permissions ||= permissions + Redmine::AccessControl.public_permissions.collect {|p| p.name}
136 @allowed_permissions ||= permissions + Redmine::AccessControl.public_permissions.collect {|p| p.name}
132 end
137 end
133
138
134 def allowed_actions
139 def allowed_actions
135 @actions_allowed ||= allowed_permissions.inject([]) { |actions, permission| actions += Redmine::AccessControl.allowed_actions(permission) }.flatten
140 @actions_allowed ||= allowed_permissions.inject([]) { |actions, permission| actions += Redmine::AccessControl.allowed_actions(permission) }.flatten
136 end
141 end
137
142
138 def check_deletable
143 def check_deletable
139 raise "Can't delete role" if members.any?
144 raise "Can't delete role" if members.any?
140 raise "Can't delete builtin role" if builtin?
145 raise "Can't delete builtin role" if builtin?
141 end
146 end
142 end
147 end
@@ -1,89 +1,89
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require 'zlib'
18 require 'zlib'
19
19
20 class WikiContent < ActiveRecord::Base
20 class WikiContent < ActiveRecord::Base
21 set_locking_column :version
21 set_locking_column :version
22 belongs_to :page, :class_name => 'WikiPage', :foreign_key => 'page_id'
22 belongs_to :page, :class_name => 'WikiPage', :foreign_key => 'page_id'
23 belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
23 belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
24 validates_presence_of :text
24 validates_presence_of :text
25
25
26 acts_as_versioned
26 acts_as_versioned
27 class Version
27 class Version
28 belongs_to :page, :class_name => '::WikiPage', :foreign_key => 'page_id'
28 belongs_to :page, :class_name => '::WikiPage', :foreign_key => 'page_id'
29 belongs_to :author, :class_name => '::User', :foreign_key => 'author_id'
29 belongs_to :author, :class_name => '::User', :foreign_key => 'author_id'
30 attr_protected :data
30 attr_protected :data
31
31
32 acts_as_event :title => Proc.new {|o| "#{l(:label_wiki_edit)}: #{o.page.title} (##{o.version})"},
32 acts_as_event :title => Proc.new {|o| "#{l(:label_wiki_edit)}: #{o.page.title} (##{o.version})"},
33 :description => :comments,
33 :description => :comments,
34 :datetime => :updated_on,
34 :datetime => :updated_on,
35 :type => 'wiki-page',
35 :type => 'wiki-page',
36 :url => Proc.new {|o| {:controller => 'wiki', :id => o.page.wiki.project_id, :page => o.page.title, :version => o.version}}
36 :url => Proc.new {|o| {:controller => 'wiki', :id => o.page.wiki.project_id, :page => o.page.title, :version => o.version}}
37
37
38 acts_as_activity_provider :type => 'wiki_pages',
38 acts_as_activity_provider :type => 'wiki_edits',
39 :timestamp => "#{WikiContent.versioned_table_name}.updated_on",
39 :timestamp => "#{WikiContent.versioned_table_name}.updated_on",
40 :permission => :view_wiki_pages,
40 :permission => :view_wiki_edits,
41 :find_options => {:select => "#{WikiContent.versioned_table_name}.updated_on, #{WikiContent.versioned_table_name}.comments, " +
41 :find_options => {:select => "#{WikiContent.versioned_table_name}.updated_on, #{WikiContent.versioned_table_name}.comments, " +
42 "#{WikiContent.versioned_table_name}.#{WikiContent.version_column}, #{WikiPage.table_name}.title, " +
42 "#{WikiContent.versioned_table_name}.#{WikiContent.version_column}, #{WikiPage.table_name}.title, " +
43 "#{WikiContent.versioned_table_name}.page_id, #{WikiContent.versioned_table_name}.author_id, " +
43 "#{WikiContent.versioned_table_name}.page_id, #{WikiContent.versioned_table_name}.author_id, " +
44 "#{WikiContent.versioned_table_name}.id",
44 "#{WikiContent.versioned_table_name}.id",
45 :joins => "LEFT JOIN #{WikiPage.table_name} ON #{WikiPage.table_name}.id = #{WikiContent.versioned_table_name}.page_id " +
45 :joins => "LEFT JOIN #{WikiPage.table_name} ON #{WikiPage.table_name}.id = #{WikiContent.versioned_table_name}.page_id " +
46 "LEFT JOIN #{Wiki.table_name} ON #{Wiki.table_name}.id = #{WikiPage.table_name}.wiki_id " +
46 "LEFT JOIN #{Wiki.table_name} ON #{Wiki.table_name}.id = #{WikiPage.table_name}.wiki_id " +
47 "LEFT JOIN #{Project.table_name} ON #{Project.table_name}.id = #{Wiki.table_name}.project_id"}
47 "LEFT JOIN #{Project.table_name} ON #{Project.table_name}.id = #{Wiki.table_name}.project_id"}
48
48
49 def text=(plain)
49 def text=(plain)
50 case Setting.wiki_compression
50 case Setting.wiki_compression
51 when 'gzip'
51 when 'gzip'
52 begin
52 begin
53 self.data = Zlib::Deflate.deflate(plain, Zlib::BEST_COMPRESSION)
53 self.data = Zlib::Deflate.deflate(plain, Zlib::BEST_COMPRESSION)
54 self.compression = 'gzip'
54 self.compression = 'gzip'
55 rescue
55 rescue
56 self.data = plain
56 self.data = plain
57 self.compression = ''
57 self.compression = ''
58 end
58 end
59 else
59 else
60 self.data = plain
60 self.data = plain
61 self.compression = ''
61 self.compression = ''
62 end
62 end
63 plain
63 plain
64 end
64 end
65
65
66 def text
66 def text
67 @text ||= case compression
67 @text ||= case compression
68 when 'gzip'
68 when 'gzip'
69 Zlib::Inflate.inflate(data)
69 Zlib::Inflate.inflate(data)
70 else
70 else
71 # uncompressed data
71 # uncompressed data
72 data
72 data
73 end
73 end
74 end
74 end
75
75
76 def project
76 def project
77 page.project
77 page.project
78 end
78 end
79
79
80 # Returns the previous version or nil
80 # Returns the previous version or nil
81 def previous
81 def previous
82 @previous ||= WikiContent::Version.find(:first,
82 @previous ||= WikiContent::Version.find(:first,
83 :order => 'version DESC',
83 :order => 'version DESC',
84 :include => :author,
84 :include => :author,
85 :conditions => ["wiki_content_id = ? AND version < ?", wiki_content_id, version])
85 :conditions => ["wiki_content_id = ? AND version < ?", wiki_content_id, version])
86 end
86 end
87 end
87 end
88
88
89 end
89 end
@@ -1,59 +1,59
1 <div class="contextual">
1 <div class="contextual">
2 <% if @editable %>
2 <% if @editable %>
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 %>
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 !@page.protected? %>
4 <%= link_to_if_authorized(l(:button_lock), {:action => 'protect', :page => @page.title, :protected => 1}, :method => :post, :class => 'icon icon-lock') if !@page.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? %>
5 <%= link_to_if_authorized(l(:button_unlock), {:action => 'protect', :page => @page.title, :protected => 0}, :method => :post, :class => 'icon icon-unlock') if @page.protected? %>
6 <%= link_to_if_authorized(l(:button_rename), {:action => 'rename', :page => @page.title}, :class => 'icon icon-move') if @content.version == @page.content.version %>
6 <%= link_to_if_authorized(l(:button_rename), {:action => 'rename', :page => @page.title}, :class => 'icon icon-move') if @content.version == @page.content.version %>
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') %>
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') %>
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 %>
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 %>
9 <% end %>
10 <%= link_to(l(:label_history), {:action => 'history', :page => @page.title}, :class => 'icon icon-history') %>
10 <%= link_to_if_authorized(l(:label_history), {:action => 'history', :page => @page.title}, :class => 'icon icon-history') %>
11 </div>
11 </div>
12
12
13 <%= breadcrumb(@page.ancestors.reverse.collect {|parent| link_to h(parent.pretty_title), {:page => parent.title}}) %>
13 <%= breadcrumb(@page.ancestors.reverse.collect {|parent| link_to h(parent.pretty_title), {:page => parent.title}}) %>
14
14
15 <% if @content.version != @page.content.version %>
15 <% if @content.version != @page.content.version %>
16 <p>
16 <p>
17 <%= link_to(('&#171; ' + l(:label_previous)), :action => 'index', :page => @page.title, :version => (@content.version - 1)) + " - " if @content.version > 1 %>
17 <%= link_to(('&#171; ' + l(:label_previous)), :action => 'index', :page => @page.title, :version => (@content.version - 1)) + " - " if @content.version > 1 %>
18 <%= "#{l(:label_version)} #{@content.version}/#{@page.content.version}" %>
18 <%= "#{l(:label_version)} #{@content.version}/#{@page.content.version}" %>
19 <%= '(' + link_to('diff', :controller => 'wiki', :action => 'diff', :page => @page.title, :version => @content.version) + ')' if @content.version > 1 %> -
19 <%= '(' + link_to('diff', :controller => 'wiki', :action => 'diff', :page => @page.title, :version => @content.version) + ')' if @content.version > 1 %> -
20 <%= link_to((l(:label_next) + ' &#187;'), :action => 'index', :page => @page.title, :version => (@content.version + 1)) + " - " if @content.version < @page.content.version %>
20 <%= link_to((l(:label_next) + ' &#187;'), :action => 'index', :page => @page.title, :version => (@content.version + 1)) + " - " if @content.version < @page.content.version %>
21 <%= link_to(l(:label_current_version), :action => 'index', :page => @page.title) %>
21 <%= link_to(l(:label_current_version), :action => 'index', :page => @page.title) %>
22 <br />
22 <br />
23 <em><%= @content.author ? @content.author.name : "anonyme" %>, <%= format_time(@content.updated_on) %> </em><br />
23 <em><%= @content.author ? @content.author.name : "anonyme" %>, <%= format_time(@content.updated_on) %> </em><br />
24 <%=h @content.comments %>
24 <%=h @content.comments %>
25 </p>
25 </p>
26 <hr />
26 <hr />
27 <% end %>
27 <% end %>
28
28
29 <%= render(:partial => "wiki/content", :locals => {:content => @content}) %>
29 <%= render(:partial => "wiki/content", :locals => {:content => @content}) %>
30
30
31 <%= link_to_attachments @page.attachments, :delete_url => ((@editable && authorize_for('wiki', 'destroy_attachment')) ? {:controller => 'wiki', :action => 'destroy_attachment', :page => @page.title} : nil) %>
31 <%= link_to_attachments @page.attachments, :delete_url => ((@editable && authorize_for('wiki', 'destroy_attachment')) ? {:controller => 'wiki', :action => 'destroy_attachment', :page => @page.title} : nil) %>
32
32
33 <% if @editable && authorize_for('wiki', 'add_attachment') %>
33 <% if @editable && authorize_for('wiki', 'add_attachment') %>
34 <p><%= link_to l(:label_attachment_new), {}, :onclick => "Element.show('add_attachment_form'); Element.hide(this); Element.scrollTo('add_attachment_form'); return false;",
34 <p><%= link_to l(:label_attachment_new), {}, :onclick => "Element.show('add_attachment_form'); Element.hide(this); Element.scrollTo('add_attachment_form'); return false;",
35 :id => 'attach_files_link' %></p>
35 :id => 'attach_files_link' %></p>
36 <% form_tag({ :controller => 'wiki', :action => 'add_attachment', :page => @page.title }, :multipart => true, :id => "add_attachment_form", :style => "display:none;") do %>
36 <% form_tag({ :controller => 'wiki', :action => 'add_attachment', :page => @page.title }, :multipart => true, :id => "add_attachment_form", :style => "display:none;") do %>
37 <div class="box">
37 <div class="box">
38 <p><%= render :partial => 'attachments/form' %></p>
38 <p><%= render :partial => 'attachments/form' %></p>
39 </div>
39 </div>
40 <%= submit_tag l(:button_add) %>
40 <%= submit_tag l(:button_add) %>
41 <%= link_to l(:button_cancel), {}, :onclick => "Element.hide('add_attachment_form'); Element.show('attach_files_link'); return false;" %>
41 <%= link_to l(:button_cancel), {}, :onclick => "Element.hide('add_attachment_form'); Element.show('attach_files_link'); return false;" %>
42 <% end %>
42 <% end %>
43 <% end %>
43 <% end %>
44
44
45 <p class="other-formats">
45 <p class="other-formats">
46 <%= l(:label_export_to) %>
46 <%= l(:label_export_to) %>
47 <span><%= link_to 'HTML', {:page => @page.title, :export => 'html', :version => @content.version}, :class => 'html' %></span>
47 <span><%= link_to 'HTML', {:page => @page.title, :export => 'html', :version => @content.version}, :class => 'html' %></span>
48 <span><%= link_to 'TXT', {:page => @page.title, :export => 'txt', :version => @content.version}, :class => 'text' %></span>
48 <span><%= link_to 'TXT', {:page => @page.title, :export => 'txt', :version => @content.version}, :class => 'text' %></span>
49 </p>
49 </p>
50
50
51 <% content_for :header_tags do %>
51 <% content_for :header_tags do %>
52 <%= stylesheet_link_tag 'scm' %>
52 <%= stylesheet_link_tag 'scm' %>
53 <% end %>
53 <% end %>
54
54
55 <% content_for :sidebar do %>
55 <% content_for :sidebar do %>
56 <%= render :partial => 'sidebar' %>
56 <%= render :partial => 'sidebar' %>
57 <% end %>
57 <% end %>
58
58
59 <% html_title @page.pretty_title %>
59 <% html_title @page.pretty_title %>
@@ -1,150 +1,151
1 require 'redmine/access_control'
1 require 'redmine/access_control'
2 require 'redmine/menu_manager'
2 require 'redmine/menu_manager'
3 require 'redmine/activity'
3 require 'redmine/activity'
4 require 'redmine/mime_type'
4 require 'redmine/mime_type'
5 require 'redmine/core_ext'
5 require 'redmine/core_ext'
6 require 'redmine/themes'
6 require 'redmine/themes'
7 require 'redmine/hook'
7 require 'redmine/hook'
8 require 'redmine/plugin'
8 require 'redmine/plugin'
9
9
10 begin
10 begin
11 require_library_or_gem 'RMagick' unless Object.const_defined?(:Magick)
11 require_library_or_gem 'RMagick' unless Object.const_defined?(:Magick)
12 rescue LoadError
12 rescue LoadError
13 # RMagick is not available
13 # RMagick is not available
14 end
14 end
15
15
16 REDMINE_SUPPORTED_SCM = %w( Subversion Darcs Mercurial Cvs Bazaar Git Filesystem )
16 REDMINE_SUPPORTED_SCM = %w( Subversion Darcs Mercurial Cvs Bazaar Git Filesystem )
17
17
18 # Permissions
18 # Permissions
19 Redmine::AccessControl.map do |map|
19 Redmine::AccessControl.map do |map|
20 map.permission :view_project, {:projects => [:show, :activity]}, :public => true
20 map.permission :view_project, {:projects => [:show, :activity]}, :public => true
21 map.permission :search_project, {:search => :index}, :public => true
21 map.permission :search_project, {:search => :index}, :public => true
22 map.permission :edit_project, {:projects => [:settings, :edit]}, :require => :member
22 map.permission :edit_project, {:projects => [:settings, :edit]}, :require => :member
23 map.permission :select_project_modules, {:projects => :modules}, :require => :member
23 map.permission :select_project_modules, {:projects => :modules}, :require => :member
24 map.permission :manage_members, {:projects => :settings, :members => [:new, :edit, :destroy]}, :require => :member
24 map.permission :manage_members, {:projects => :settings, :members => [:new, :edit, :destroy]}, :require => :member
25 map.permission :manage_versions, {:projects => [:settings, :add_version], :versions => [:edit, :destroy]}, :require => :member
25 map.permission :manage_versions, {:projects => [:settings, :add_version], :versions => [:edit, :destroy]}, :require => :member
26
26
27 map.project_module :issue_tracking do |map|
27 map.project_module :issue_tracking do |map|
28 # Issue categories
28 # Issue categories
29 map.permission :manage_categories, {:projects => [:settings, :add_issue_category], :issue_categories => [:edit, :destroy]}, :require => :member
29 map.permission :manage_categories, {:projects => [:settings, :add_issue_category], :issue_categories => [:edit, :destroy]}, :require => :member
30 # Issues
30 # Issues
31 map.permission :view_issues, {:projects => [:changelog, :roadmap],
31 map.permission :view_issues, {:projects => [:changelog, :roadmap],
32 :issues => [:index, :changes, :show, :context_menu],
32 :issues => [:index, :changes, :show, :context_menu],
33 :versions => [:show, :status_by],
33 :versions => [:show, :status_by],
34 :queries => :index,
34 :queries => :index,
35 :reports => :issue_report}, :public => true
35 :reports => :issue_report}, :public => true
36 map.permission :add_issues, {:issues => :new}
36 map.permission :add_issues, {:issues => :new}
37 map.permission :edit_issues, {:issues => [:edit, :reply, :bulk_edit, :destroy_attachment]}
37 map.permission :edit_issues, {:issues => [:edit, :reply, :bulk_edit, :destroy_attachment]}
38 map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]}
38 map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]}
39 map.permission :add_issue_notes, {:issues => [:edit, :reply]}
39 map.permission :add_issue_notes, {:issues => [:edit, :reply]}
40 map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin
40 map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin
41 map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin
41 map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin
42 map.permission :move_issues, {:issues => :move}, :require => :loggedin
42 map.permission :move_issues, {:issues => :move}, :require => :loggedin
43 map.permission :delete_issues, {:issues => :destroy}, :require => :member
43 map.permission :delete_issues, {:issues => :destroy}, :require => :member
44 # Queries
44 # Queries
45 map.permission :manage_public_queries, {:queries => [:new, :edit, :destroy]}, :require => :member
45 map.permission :manage_public_queries, {:queries => [:new, :edit, :destroy]}, :require => :member
46 map.permission :save_queries, {:queries => [:new, :edit, :destroy]}, :require => :loggedin
46 map.permission :save_queries, {:queries => [:new, :edit, :destroy]}, :require => :loggedin
47 # Gantt & calendar
47 # Gantt & calendar
48 map.permission :view_gantt, :issues => :gantt
48 map.permission :view_gantt, :issues => :gantt
49 map.permission :view_calendar, :issues => :calendar
49 map.permission :view_calendar, :issues => :calendar
50 # Watchers
50 # Watchers
51 map.permission :view_issue_watchers, {}
51 map.permission :view_issue_watchers, {}
52 map.permission :add_issue_watchers, {:watchers => :new}
52 map.permission :add_issue_watchers, {:watchers => :new}
53 end
53 end
54
54
55 map.project_module :time_tracking do |map|
55 map.project_module :time_tracking do |map|
56 map.permission :log_time, {:timelog => :edit}, :require => :loggedin
56 map.permission :log_time, {:timelog => :edit}, :require => :loggedin
57 map.permission :view_time_entries, :timelog => [:details, :report]
57 map.permission :view_time_entries, :timelog => [:details, :report]
58 map.permission :edit_time_entries, {:timelog => [:edit, :destroy]}, :require => :member
58 map.permission :edit_time_entries, {:timelog => [:edit, :destroy]}, :require => :member
59 map.permission :edit_own_time_entries, {:timelog => [:edit, :destroy]}, :require => :loggedin
59 map.permission :edit_own_time_entries, {:timelog => [:edit, :destroy]}, :require => :loggedin
60 end
60 end
61
61
62 map.project_module :news do |map|
62 map.project_module :news do |map|
63 map.permission :manage_news, {:news => [:new, :edit, :destroy, :destroy_comment]}, :require => :member
63 map.permission :manage_news, {:news => [:new, :edit, :destroy, :destroy_comment]}, :require => :member
64 map.permission :view_news, {:news => [:index, :show]}, :public => true
64 map.permission :view_news, {:news => [:index, :show]}, :public => true
65 map.permission :comment_news, {:news => :add_comment}
65 map.permission :comment_news, {:news => :add_comment}
66 end
66 end
67
67
68 map.project_module :documents do |map|
68 map.project_module :documents do |map|
69 map.permission :manage_documents, {:documents => [:new, :edit, :destroy, :add_attachment, :destroy_attachment]}, :require => :loggedin
69 map.permission :manage_documents, {:documents => [:new, :edit, :destroy, :add_attachment, :destroy_attachment]}, :require => :loggedin
70 map.permission :view_documents, :documents => [:index, :show, :download]
70 map.permission :view_documents, :documents => [:index, :show, :download]
71 end
71 end
72
72
73 map.project_module :files do |map|
73 map.project_module :files do |map|
74 map.permission :manage_files, {:projects => :add_file, :versions => :destroy_file}, :require => :loggedin
74 map.permission :manage_files, {:projects => :add_file, :versions => :destroy_file}, :require => :loggedin
75 map.permission :view_files, :projects => :list_files, :versions => :download
75 map.permission :view_files, :projects => :list_files, :versions => :download
76 end
76 end
77
77
78 map.project_module :wiki do |map|
78 map.project_module :wiki do |map|
79 map.permission :manage_wiki, {:wikis => [:edit, :destroy]}, :require => :member
79 map.permission :manage_wiki, {:wikis => [:edit, :destroy]}, :require => :member
80 map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member
80 map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member
81 map.permission :delete_wiki_pages, {:wiki => :destroy}, :require => :member
81 map.permission :delete_wiki_pages, {:wiki => :destroy}, :require => :member
82 map.permission :view_wiki_pages, :wiki => [:index, :history, :diff, :annotate, :special]
82 map.permission :view_wiki_pages, :wiki => [:index, :special]
83 map.permission :view_wiki_edits, :wiki => [:history, :diff, :annotate]
83 map.permission :edit_wiki_pages, :wiki => [:edit, :preview, :add_attachment, :destroy_attachment]
84 map.permission :edit_wiki_pages, :wiki => [:edit, :preview, :add_attachment, :destroy_attachment]
84 map.permission :protect_wiki_pages, {:wiki => :protect}, :require => :member
85 map.permission :protect_wiki_pages, {:wiki => :protect}, :require => :member
85 end
86 end
86
87
87 map.project_module :repository do |map|
88 map.project_module :repository do |map|
88 map.permission :manage_repository, {:repositories => [:edit, :destroy]}, :require => :member
89 map.permission :manage_repository, {:repositories => [:edit, :destroy]}, :require => :member
89 map.permission :browse_repository, :repositories => [:show, :browse, :entry, :annotate, :changes, :diff, :stats, :graph]
90 map.permission :browse_repository, :repositories => [:show, :browse, :entry, :annotate, :changes, :diff, :stats, :graph]
90 map.permission :view_changesets, :repositories => [:show, :revisions, :revision]
91 map.permission :view_changesets, :repositories => [:show, :revisions, :revision]
91 map.permission :commit_access, {}
92 map.permission :commit_access, {}
92 end
93 end
93
94
94 map.project_module :boards do |map|
95 map.project_module :boards do |map|
95 map.permission :manage_boards, {:boards => [:new, :edit, :destroy]}, :require => :member
96 map.permission :manage_boards, {:boards => [:new, :edit, :destroy]}, :require => :member
96 map.permission :view_messages, {:boards => [:index, :show], :messages => [:show]}, :public => true
97 map.permission :view_messages, {:boards => [:index, :show], :messages => [:show]}, :public => true
97 map.permission :add_messages, {:messages => [:new, :reply, :quote]}
98 map.permission :add_messages, {:messages => [:new, :reply, :quote]}
98 map.permission :edit_messages, {:messages => :edit}, :require => :member
99 map.permission :edit_messages, {:messages => :edit}, :require => :member
99 map.permission :delete_messages, {:messages => :destroy}, :require => :member
100 map.permission :delete_messages, {:messages => :destroy}, :require => :member
100 end
101 end
101 end
102 end
102
103
103 Redmine::MenuManager.map :top_menu do |menu|
104 Redmine::MenuManager.map :top_menu do |menu|
104 menu.push :home, :home_path, :html => { :class => 'home' }
105 menu.push :home, :home_path, :html => { :class => 'home' }
105 menu.push :my_page, { :controller => 'my', :action => 'page' }, :html => { :class => 'mypage' }, :if => Proc.new { User.current.logged? }
106 menu.push :my_page, { :controller => 'my', :action => 'page' }, :html => { :class => 'mypage' }, :if => Proc.new { User.current.logged? }
106 menu.push :projects, { :controller => 'projects', :action => 'index' }, :caption => :label_project_plural, :html => { :class => 'projects' }
107 menu.push :projects, { :controller => 'projects', :action => 'index' }, :caption => :label_project_plural, :html => { :class => 'projects' }
107 menu.push :administration, { :controller => 'admin', :action => 'index' }, :html => { :class => 'admin' }, :if => Proc.new { User.current.admin? }, :last => true
108 menu.push :administration, { :controller => 'admin', :action => 'index' }, :html => { :class => 'admin' }, :if => Proc.new { User.current.admin? }, :last => true
108 menu.push :help, Redmine::Info.help_url, :html => { :class => 'help' }, :last => true
109 menu.push :help, Redmine::Info.help_url, :html => { :class => 'help' }, :last => true
109 end
110 end
110
111
111 Redmine::MenuManager.map :account_menu do |menu|
112 Redmine::MenuManager.map :account_menu do |menu|
112 menu.push :login, :signin_path, :html => { :class => 'login' }, :if => Proc.new { !User.current.logged? }
113 menu.push :login, :signin_path, :html => { :class => 'login' }, :if => Proc.new { !User.current.logged? }
113 menu.push :register, { :controller => 'account', :action => 'register' }, :html => { :class => 'register' }, :if => Proc.new { !User.current.logged? && Setting.self_registration? }
114 menu.push :register, { :controller => 'account', :action => 'register' }, :html => { :class => 'register' }, :if => Proc.new { !User.current.logged? && Setting.self_registration? }
114 menu.push :my_account, { :controller => 'my', :action => 'account' }, :html => { :class => 'myaccount' }, :if => Proc.new { User.current.logged? }
115 menu.push :my_account, { :controller => 'my', :action => 'account' }, :html => { :class => 'myaccount' }, :if => Proc.new { User.current.logged? }
115 menu.push :logout, :signout_path, :html => { :class => 'logout' }, :if => Proc.new { User.current.logged? }
116 menu.push :logout, :signout_path, :html => { :class => 'logout' }, :if => Proc.new { User.current.logged? }
116 end
117 end
117
118
118 Redmine::MenuManager.map :application_menu do |menu|
119 Redmine::MenuManager.map :application_menu do |menu|
119 # Empty
120 # Empty
120 end
121 end
121
122
122 Redmine::MenuManager.map :project_menu do |menu|
123 Redmine::MenuManager.map :project_menu do |menu|
123 menu.push :overview, { :controller => 'projects', :action => 'show' }
124 menu.push :overview, { :controller => 'projects', :action => 'show' }
124 menu.push :activity, { :controller => 'projects', :action => 'activity' }
125 menu.push :activity, { :controller => 'projects', :action => 'activity' }
125 menu.push :roadmap, { :controller => 'projects', :action => 'roadmap' },
126 menu.push :roadmap, { :controller => 'projects', :action => 'roadmap' },
126 :if => Proc.new { |p| p.versions.any? }
127 :if => Proc.new { |p| p.versions.any? }
127 menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural
128 menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural
128 menu.push :new_issue, { :controller => 'issues', :action => 'new' }, :param => :project_id, :caption => :label_issue_new,
129 menu.push :new_issue, { :controller => 'issues', :action => 'new' }, :param => :project_id, :caption => :label_issue_new,
129 :html => { :accesskey => Redmine::AccessKeys.key_for(:new_issue) }
130 :html => { :accesskey => Redmine::AccessKeys.key_for(:new_issue) }
130 menu.push :news, { :controller => 'news', :action => 'index' }, :param => :project_id, :caption => :label_news_plural
131 menu.push :news, { :controller => 'news', :action => 'index' }, :param => :project_id, :caption => :label_news_plural
131 menu.push :documents, { :controller => 'documents', :action => 'index' }, :param => :project_id, :caption => :label_document_plural
132 menu.push :documents, { :controller => 'documents', :action => 'index' }, :param => :project_id, :caption => :label_document_plural
132 menu.push :wiki, { :controller => 'wiki', :action => 'index', :page => nil },
133 menu.push :wiki, { :controller => 'wiki', :action => 'index', :page => nil },
133 :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
134 :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
134 menu.push :boards, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id,
135 menu.push :boards, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id,
135 :if => Proc.new { |p| p.boards.any? }, :caption => :label_board_plural
136 :if => Proc.new { |p| p.boards.any? }, :caption => :label_board_plural
136 menu.push :files, { :controller => 'projects', :action => 'list_files' }, :caption => :label_attachment_plural
137 menu.push :files, { :controller => 'projects', :action => 'list_files' }, :caption => :label_attachment_plural
137 menu.push :repository, { :controller => 'repositories', :action => 'show' },
138 menu.push :repository, { :controller => 'repositories', :action => 'show' },
138 :if => Proc.new { |p| p.repository && !p.repository.new_record? }
139 :if => Proc.new { |p| p.repository && !p.repository.new_record? }
139 menu.push :settings, { :controller => 'projects', :action => 'settings' }, :last => true
140 menu.push :settings, { :controller => 'projects', :action => 'settings' }, :last => true
140 end
141 end
141
142
142 Redmine::Activity.map do |activity|
143 Redmine::Activity.map do |activity|
143 activity.register :issues, :class_name => %w(Issue Journal)
144 activity.register :issues, :class_name => %w(Issue Journal)
144 activity.register :changesets
145 activity.register :changesets
145 activity.register :news
146 activity.register :news
146 activity.register :documents, :class_name => %w(Document Attachment)
147 activity.register :documents, :class_name => %w(Document Attachment)
147 activity.register :files, :class_name => 'Attachment'
148 activity.register :files, :class_name => 'Attachment'
148 activity.register :wiki_pages, :class_name => 'WikiContent::Version', :default => false
149 activity.register :wiki_edits, :class_name => 'WikiContent::Version', :default => false
149 activity.register :messages, :default => false
150 activity.register :messages, :default => false
150 end
151 end
@@ -1,167 +1,172
1 ---
1 ---
2 roles_001:
2 roles_001:
3 name: Manager
3 name: Manager
4 id: 1
4 id: 1
5 builtin: 0
5 builtin: 0
6 permissions: |
6 permissions: |
7 ---
7 ---
8 - :edit_project
8 - :edit_project
9 - :manage_members
9 - :manage_members
10 - :manage_versions
10 - :manage_versions
11 - :manage_categories
11 - :manage_categories
12 - :add_issues
12 - :add_issues
13 - :edit_issues
13 - :edit_issues
14 - :manage_issue_relations
14 - :manage_issue_relations
15 - :add_issue_notes
15 - :add_issue_notes
16 - :move_issues
16 - :move_issues
17 - :delete_issues
17 - :delete_issues
18 - :view_issue_watchers
18 - :view_issue_watchers
19 - :add_issue_watchers
19 - :add_issue_watchers
20 - :manage_public_queries
20 - :manage_public_queries
21 - :save_queries
21 - :save_queries
22 - :view_gantt
22 - :view_gantt
23 - :view_calendar
23 - :view_calendar
24 - :log_time
24 - :log_time
25 - :view_time_entries
25 - :view_time_entries
26 - :edit_time_entries
26 - :edit_time_entries
27 - :delete_time_entries
27 - :delete_time_entries
28 - :manage_news
28 - :manage_news
29 - :comment_news
29 - :comment_news
30 - :view_documents
30 - :view_documents
31 - :manage_documents
31 - :manage_documents
32 - :view_wiki_pages
32 - :view_wiki_pages
33 - :view_wiki_edits
33 - :edit_wiki_pages
34 - :edit_wiki_pages
34 - :protect_wiki_pages
35 - :protect_wiki_pages
35 - :delete_wiki_pages
36 - :delete_wiki_pages
36 - :rename_wiki_pages
37 - :rename_wiki_pages
37 - :add_messages
38 - :add_messages
38 - :edit_messages
39 - :edit_messages
39 - :delete_messages
40 - :delete_messages
40 - :manage_boards
41 - :manage_boards
41 - :view_files
42 - :view_files
42 - :manage_files
43 - :manage_files
43 - :browse_repository
44 - :browse_repository
44 - :view_changesets
45 - :view_changesets
45
46
46 position: 1
47 position: 1
47 roles_002:
48 roles_002:
48 name: Developer
49 name: Developer
49 id: 2
50 id: 2
50 builtin: 0
51 builtin: 0
51 permissions: |
52 permissions: |
52 ---
53 ---
53 - :edit_project
54 - :edit_project
54 - :manage_members
55 - :manage_members
55 - :manage_versions
56 - :manage_versions
56 - :manage_categories
57 - :manage_categories
57 - :add_issues
58 - :add_issues
58 - :edit_issues
59 - :edit_issues
59 - :manage_issue_relations
60 - :manage_issue_relations
60 - :add_issue_notes
61 - :add_issue_notes
61 - :move_issues
62 - :move_issues
62 - :delete_issues
63 - :delete_issues
63 - :view_issue_watchers
64 - :view_issue_watchers
64 - :save_queries
65 - :save_queries
65 - :view_gantt
66 - :view_gantt
66 - :view_calendar
67 - :view_calendar
67 - :log_time
68 - :log_time
68 - :view_time_entries
69 - :view_time_entries
69 - :edit_own_time_entries
70 - :edit_own_time_entries
70 - :manage_news
71 - :manage_news
71 - :comment_news
72 - :comment_news
72 - :view_documents
73 - :view_documents
73 - :manage_documents
74 - :manage_documents
74 - :view_wiki_pages
75 - :view_wiki_pages
76 - :view_wiki_edits
75 - :edit_wiki_pages
77 - :edit_wiki_pages
76 - :protect_wiki_pages
78 - :protect_wiki_pages
77 - :delete_wiki_pages
79 - :delete_wiki_pages
78 - :add_messages
80 - :add_messages
79 - :manage_boards
81 - :manage_boards
80 - :view_files
82 - :view_files
81 - :manage_files
83 - :manage_files
82 - :browse_repository
84 - :browse_repository
83 - :view_changesets
85 - :view_changesets
84
86
85 position: 2
87 position: 2
86 roles_003:
88 roles_003:
87 name: Reporter
89 name: Reporter
88 id: 3
90 id: 3
89 builtin: 0
91 builtin: 0
90 permissions: |
92 permissions: |
91 ---
93 ---
92 - :edit_project
94 - :edit_project
93 - :manage_members
95 - :manage_members
94 - :manage_versions
96 - :manage_versions
95 - :manage_categories
97 - :manage_categories
96 - :add_issues
98 - :add_issues
97 - :edit_issues
99 - :edit_issues
98 - :manage_issue_relations
100 - :manage_issue_relations
99 - :add_issue_notes
101 - :add_issue_notes
100 - :move_issues
102 - :move_issues
101 - :view_issue_watchers
103 - :view_issue_watchers
102 - :save_queries
104 - :save_queries
103 - :view_gantt
105 - :view_gantt
104 - :view_calendar
106 - :view_calendar
105 - :log_time
107 - :log_time
106 - :view_time_entries
108 - :view_time_entries
107 - :manage_news
109 - :manage_news
108 - :comment_news
110 - :comment_news
109 - :view_documents
111 - :view_documents
110 - :manage_documents
112 - :manage_documents
111 - :view_wiki_pages
113 - :view_wiki_pages
114 - :view_wiki_edits
112 - :edit_wiki_pages
115 - :edit_wiki_pages
113 - :delete_wiki_pages
116 - :delete_wiki_pages
114 - :add_messages
117 - :add_messages
115 - :manage_boards
118 - :manage_boards
116 - :view_files
119 - :view_files
117 - :manage_files
120 - :manage_files
118 - :browse_repository
121 - :browse_repository
119 - :view_changesets
122 - :view_changesets
120
123
121 position: 3
124 position: 3
122 roles_004:
125 roles_004:
123 name: Non member
126 name: Non member
124 id: 4
127 id: 4
125 builtin: 1
128 builtin: 1
126 permissions: |
129 permissions: |
127 ---
130 ---
128 - :add_issues
131 - :add_issues
129 - :edit_issues
132 - :edit_issues
130 - :manage_issue_relations
133 - :manage_issue_relations
131 - :add_issue_notes
134 - :add_issue_notes
132 - :move_issues
135 - :move_issues
133 - :save_queries
136 - :save_queries
134 - :view_gantt
137 - :view_gantt
135 - :view_calendar
138 - :view_calendar
136 - :log_time
139 - :log_time
137 - :view_time_entries
140 - :view_time_entries
138 - :comment_news
141 - :comment_news
139 - :view_documents
142 - :view_documents
140 - :manage_documents
143 - :manage_documents
141 - :view_wiki_pages
144 - :view_wiki_pages
145 - :view_wiki_edits
142 - :edit_wiki_pages
146 - :edit_wiki_pages
143 - :add_messages
147 - :add_messages
144 - :view_files
148 - :view_files
145 - :manage_files
149 - :manage_files
146 - :browse_repository
150 - :browse_repository
147 - :view_changesets
151 - :view_changesets
148
152
149 position: 4
153 position: 4
150 roles_005:
154 roles_005:
151 name: Anonymous
155 name: Anonymous
152 id: 5
156 id: 5
153 builtin: 2
157 builtin: 2
154 permissions: |
158 permissions: |
155 ---
159 ---
156 - :add_issue_notes
160 - :add_issue_notes
157 - :view_gantt
161 - :view_gantt
158 - :view_calendar
162 - :view_calendar
159 - :view_time_entries
163 - :view_time_entries
160 - :view_documents
164 - :view_documents
161 - :view_wiki_pages
165 - :view_wiki_pages
166 - :view_wiki_edits
162 - :view_files
167 - :view_files
163 - :browse_repository
168 - :browse_repository
164 - :view_changesets
169 - :view_changesets
165
170
166 position: 5
171 position: 5
167 No newline at end of file
172
General Comments 0
You need to be logged in to leave comments. Login now