465-shared-versions-work-in-progress.patch

Shared versions patch, check Github for the latest - Eric Davis, 2009-09-03 23:46

Download (30.9 KB)

View differences:

app/controllers/issues_controller.rb
240 240
      priority = params[:priority_id].blank? ? nil : IssuePriority.find_by_id(params[:priority_id])
241 241
      assigned_to = (params[:assigned_to_id].blank? || params[:assigned_to_id] == 'none') ? nil : User.find_by_id(params[:assigned_to_id])
242 242
      category = (params[:category_id].blank? || params[:category_id] == 'none') ? nil : @project.issue_categories.find_by_id(params[:category_id])
243
      fixed_version = (params[:fixed_version_id].blank? || params[:fixed_version_id] == 'none') ? nil : @project.versions.find_by_id(params[:fixed_version_id])
243
      fixed_version = (params[:fixed_version_id].blank? || params[:fixed_version_id] == 'none') ? nil : @project.inherited_versions.find {|v| v.id.to_s == params[:fixed_version_id] }
244 244
      custom_field_values = params[:custom_field_values] ? params[:custom_field_values].reject {|k,v| v.blank?} : nil
245 245
      
246 246
      unsaved_issue_ids = []      
app/controllers/projects_controller.rb
240 240
                'downloads' => "#{Attachment.table_name}.downloads"
241 241
                
242 242
    @containers = [ Project.find(@project.id, :include => :attachments, :order => sort_clause)]
243
    @containers += @project.versions.find(:all, :include => :attachments, :order => sort_clause).sort.reverse
243
    # Need get the ids separately in order to add the finder options
244
    version_ids = @project.inherited_versions_visible_to_user.collect(&:id)
245
    @containers += Version.find_all_by_id(version_ids, :include => :attachments, :order => sort_clause).sort.reverse
244 246
    render :layout => !request.xhr?
245 247
  end
246 248
  
......
248 250
  def changelog
249 251
    @trackers = @project.trackers.find(:all, :conditions => ["is_in_chlog=?", true], :order => 'position')
250 252
    retrieve_selected_tracker_ids(@trackers)    
251
    @versions = @project.versions.sort
253
    if params[:inherited_versions]
254
      @versions = @project.inherited_versions_visible_to_user.sort
255
    else
256
      @versions = @project.versions.sort
257
    end
252 258
  end
253 259

  
254 260
  def roadmap
255 261
    @trackers = @project.trackers.find(:all, :conditions => ["is_in_roadmap=?", true])
256 262
    retrieve_selected_tracker_ids(@trackers)
257
    @versions = @project.versions.sort
263
    if params[:inherited_versions]
264
      @versions = @project.inherited_versions_visible_to_user.sort
265
    else
266
      @versions = @project.versions.sort
267
    end
258 268
    @versions = @versions.select {|v| !v.completed? } unless params[:completed]
259 269
  end
260 270
  
app/helpers/application_helper.rb
97 97
    h(truncate(text.to_s, :length => 120).gsub(%r{[\r\n]*<(pre|code)>.*$}m, '...')).gsub(/[\r\n]+/, "<br />")
98 98
  end
99 99

  
100
  def format_version_name(version)
101
    if User.current.allowed_to?(:view_issues, version.project)
102
      "#{h(version.project.name)} - #{h(version.name)}"
103
    else
104
      "#{l(:text_not_authorized)}"
105
    end
106
  end
107

  
108
  # Given an Array of emails (+recipients+), do they all have
109
  # +permission+ on +project+ ?
110
  def recipients_all_allowed_to?(recipients, permission, project)
111
    recipients.uniq.all? do |recipient|
112
      user = User.find_by_mail(recipient)
113
      user && user.allowed_to?(permission, project)
114
    end
115
  end
116

  
117
  # Given an Array of +versions+, are all the email addresses
118
  # (+recipients+) allowed to view all of the versions?
119
  def recipients_all_allowed_to_see_versions?(recipients, versions)
120
    versions.uniq.all? do |version|
121
      if version.nil?
122
        true
123
      else
124
        recipients_all_allowed_to?(recipients, :view_issues, version.project)
125
      end
126
    end
127
  end
128
  
100 129
  def due_date_distance_in_words(date)
101 130
    if date
102 131
      l((date < Date.today ? :label_roadmap_overdue : :label_roadmap_due_in), distance_of_date_in_words(Date.today, date))
app/helpers/issues_helper.rb
66 66
    @sidebar_queries
67 67
  end
68 68

  
69
  def inherited_version_options(project)
70
    project.inherited_versions.sort.collect {|v| [format_version_name(v), v.id] }
71
  end
72

  
69 73
  def show_detail(detail, no_html=false)
70 74
    case detail.property
71 75
    when 'attr'
......
93 97
        c = IssueCategory.find_by_id(detail.value) and value = c.name if detail.value
94 98
        c = IssueCategory.find_by_id(detail.old_value) and old_value = c.name if detail.old_value
95 99
      when 'fixed_version_id'
96
        v = Version.find_by_id(detail.value) and value = v.name if detail.value
97
        v = Version.find_by_id(detail.old_value) and old_value = v.name if detail.old_value
100
        v = Version.find_by_id(detail.value) and value = format_version_name(v) if detail.value
101
        v = Version.find_by_id(detail.old_value) and old_value = format_version_name(v) if detail.old_value
98 102
      when 'estimated_hours'
99 103
        value = "%0.02f" % detail.value.to_f unless detail.value.blank?
100 104
        old_value = "%0.02f" % detail.old_value.to_f unless detail.old_value.blank?
app/helpers/mailer_helper.rb
1
# redMine - project management software
2
# Copyright (C) 2006-2009  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
# 
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
# 
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
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

  
18
module MailerHelper
19
  def unauthorized_version?(journal_detail, recipients)
20
    return false unless journal_detail.prop_key == "fixed_version_id"
21

  
22
    !recipients_all_allowed_to_see_versions?(recipients,
23
                                             Version.find_all_by_id([journal_detail.value, journal_detail.old_value]))
24
  end
25
end
app/helpers/projects_helper.rb
18 18
module ProjectsHelper
19 19
  def link_to_version(version, options = {})
20 20
    return '' unless version && version.is_a?(Version)
21
    link_to h(version.name), { :controller => 'versions', :action => 'show', :id => version }, options
21
    if User.current.allowed_to?(:view_issues, version.project)
22
      link_to format_version_name(version), { :controller => 'versions', :action => 'show', :id => version }, options
23
    else
24
      format_version_name(version)
25
    end
22 26
  end
23 27
  
24 28
  def project_settings_tabs
app/models/mailer.rb
19 19
  helper :application
20 20
  helper :issues
21 21
  helper :custom_fields
22
  helper :mailer
22 23

  
23 24
  include ActionController::UrlWriter
24 25
  include Redmine::I18n
app/models/project.rb
247 247
                         :conditions => ["#{Project.table_name}.lft >= ? AND #{Project.table_name}.rgt <= ? AND #{Project.table_name}.status = #{STATUS_ACTIVE}", lft, rgt],
248 248
                         :order => "#{Tracker.table_name}.position")
249 249
  end
250

  
251
  # Returns an array of the Versions used by the project, its active
252
  # sub projects, and its active parent projects
253
  def inherited_versions
254
    @inherited_versions ||= self.root.self_and_descendants.
255
      delete_if {|p| !p.active? }.
256
      collect(&:versions).
257
      flatten.
258
      sort
259

  
260
    yield @inherited_versions if block_given?
261
    @inherited_versions
262
  end
263

  
264
  # Returns the inherited_versions that are visible to +user+
265
  def inherited_versions_visible_to_user(user=User.current)
266
    return inherited_versions do |versions|
267
      versions.delete_if {|v| !user.allowed_to?(:view_issues, v.project) }
268
    end
269
  end
250 270
  
251 271
  # Returns a hash of project users grouped by role
252 272
  def users_by_role
app/models/query.rb
182 182
        @available_filters["category_id"] = { :type => :list_optional, :order => 6, :values => @project.issue_categories.collect{|s| [s.name, s.id.to_s] } }
183 183
      end
184 184
      unless @project.versions.empty?
185
        @available_filters["fixed_version_id"] = { :type => :list_optional, :order => 7, :values => @project.versions.sort.collect{|s| [s.name, s.id.to_s] } }
185
        @available_filters["fixed_version_id"] = { :type => :list_optional, :order => 7, :values => @project.inherited_versions.sort.collect{|s| ["#{s.project.name} - #{s.name}", s.id.to_s] } }
186 186
      end
187 187
      unless @project.descendants.active.empty?
188 188
        @available_filters["subproject_id"] = { :type => :list_subprojects, :order => 13, :values => @project.descendants.visible.collect{|s| [s.name, s.id.to_s] } }
app/views/issues/_form.rhtml
33 33
                     :class => 'small', :tabindex => 199) if authorize_for('projects', 'add_issue_category') %></p>
34 34
<% end %>
35 35
<%= content_tag('p', f.select(:fixed_version_id, 
36
                              (@project.versions.sort.collect {|v| [v.name, v.id]}),
37
                              { :include_blank => true })) unless @project.versions.empty? %>
36
                              (inherited_version_options(@project)),
37
                              { :include_blank => true })) unless @project.inherited_versions.empty? %>
38 38
</div>
39 39

  
40 40
<div class="splitcontentright">
app/views/issues/bulk_edit.rhtml
27 27
<label><%= l(:field_fixed_version) %>: 
28 28
<%= select_tag('fixed_version_id', content_tag('option', l(:label_no_change_option), :value => '') +
29 29
                                   content_tag('option', l(:label_none), :value => 'none') +
30
                                   options_from_collection_for_select(@project.versions.sort, :id, :name)) %></label>
30
                                   options_for_select(inherited_version_options(@project))) %></label>
31 31
</p>
32 32

  
33 33
<p>
app/views/issues/context_menu.rhtml
27 27
		<% end -%>
28 28
		</ul>
29 29
	</li>
30
	<% unless @project.nil? || @project.versions.empty? -%>
30
	<% unless @project.nil? || @project.inherited_versions.empty? -%>
31 31
	<li class="folder">			
32 32
		<a href="#" class="submenu"><%= l(:field_fixed_version) %></a>
33 33
		<ul>
34
		<% @project.versions.sort.each do |v| -%>
35
		    <li><%= context_menu_link v.name, {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id), 'fixed_version_id' => v, :back_to => @back}, :method => :post,
34
		<% @project.inherited_versions.sort.each do |v| -%>
35
		    <li><%= context_menu_link format_version_name(v), {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id), 'fixed_version_id' => v, :back_to => @back}, :method => :post,
36 36
		                              :selected => (@issue && v == @issue.fixed_version), :disabled => !@can[:update] %></li>
37 37
		<% end -%>
38 38
		    <li><%= context_menu_link l(:label_none), {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id), 'fixed_version_id' => 'none', :back_to => @back}, :method => :post,
app/views/mailer/issue_edit.text.html.rhtml
2 2

  
3 3
<ul>
4 4
<% for detail in @journal.details %>
5
<% if unauthorized_version?(detail, @recipients + @cc) %>
6
    <li><%= l(:field_fixed_version) %> <%= l(:text_journal_set_to, l(:text_not_authorized)) %></li>
7
    <% else %>
5 8
    <li><%= show_detail(detail, true) %></li>
9
    <% end %>
6 10
<% end %>
7 11
</ul>
8 12

  
app/views/mailer/issue_edit.text.plain.rhtml
1 1
<%= l(:text_issue_updated, :id => "##{@issue.id}", :author => @journal.user) %>
2 2

  
3 3
<% for detail in @journal.details -%>
4
<% if unauthorized_version?(detail, @recipients + @cc) %>
5
<%= l(:field_fixed_version) %> <%= l(:text_journal_set_to, l(:text_not_authorized)) %>
6
<% else %>
4 7
<%= show_detail(detail, true) %>
8
<% end %>
5 9
<% end -%>
6 10

  
7 11
<%= @journal.notes if @journal.notes? %>
app/views/projects/changelog.rhtml
32 32
  <label><%= check_box_tag "tracker_ids[]", tracker.id, (@selected_tracker_ids.include? tracker.id.to_s) %>
33 33
  <%= tracker.name %></label><br />
34 34
<% end %>
35
<br />
36
<label for="inherited_versions"><%= check_box_tag "inherited_versions", 1, params[:inherited_versions] %> <%= l(:label_show_inherited_versions) %></label>
35 37
<p><%= submit_tag l(:button_apply), :class => 'button-small' %></p>
36 38
<% end %>
37 39

  
app/views/projects/list_files.rhtml
21 21
	<% if container.is_a?(Version) -%>
22 22
  <tr>
23 23
  	<th colspan="6" align="left">
24
  		<%= link_to(h(container), {:controller => 'versions', :action => 'show', :id => container}, :class => "icon icon-package") %>
24
  		<%= link_to(h(container.project.name) + ' - ' + h(container), {:controller => 'versions', :action => 'show', :id => container}, :class => "icon icon-package") %>
25 25
		</th>
26 26
	</tr>
27 27
	<% end -%>
app/views/projects/roadmap.rhtml
6 6
<div id="roadmap">
7 7
<% @versions.each do |version| %>   
8 8
    <%= tag 'a', :name => version.name %>
9
    <h3 class="icon22 icon22-package"><%= link_to h(version.name), :controller => 'versions', :action => 'show', :id => version %></h3>
9
    <h3 class="icon22 icon22-package"><%= link_to h(version.project.name) + " - " + h(version.name), :controller => 'versions', :action => 'show', :id => version %></h3>
10 10
    <%= render :partial => 'versions/overview', :locals => {:version => version} %>
11 11
    <%= render(:partial => "wiki/content", :locals => {:content => version.wiki_page.content}) if version.wiki_page %>
12 12

  
......
39 39
<% end %>
40 40
<br />
41 41
<label for="completed"><%= check_box_tag "completed", 1, params[:completed] %> <%= l(:label_show_completed_versions) %></label>
42
<br />
43
<label for="inherited_versions"><%= check_box_tag "inherited_versions", 1, params[:inherited_versions] %> <%= l(:label_show_inherited_versions) %></label>
42 44
<p><%= submit_tag l(:button_apply), :class => 'button-small', :name => nil %></p>
43 45
<% end %>
44 46

  
config/locales/en.yml
615 615
  label_stay_logged_in: Stay logged in
616 616
  label_disabled: disabled
617 617
  label_show_completed_versions: Show completed versions
618
  label_show_inherited_versions: Show inherited versions
618 619
  label_me: me
619 620
  label_board: Forum
620 621
  label_board_new: New forum
......
778 779
  text_wiki_page_nullify_children: "Keep child pages as root pages"
779 780
  text_wiki_page_destroy_children: "Delete child pages and all their descendants"
780 781
  text_wiki_page_reassign_children: "Reassign child pages to this parent page"
782
  text_not_authorized: You are not authorized to view this.
783

  
781 784
  
782 785
  default_role_manager: Manager
783 786
  default_role_developper: Developer
test/fixtures/attachments.yml
121 121
  filename: picture.jpg
122 122
  author_id: 2
123 123
  content_type: image/jpeg
124
  
124
attachments_011: 
125
  created_on: 2006-07-19 21:07:27 +02:00
126
  container_type: Version
127
  container_id: 1
128
  downloads: 0
129
  disk_filename: 060719210727_version_file.zip
130
  digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
131
  id: 11
132
  filesize: 452
133
  filename: version_file.zip
134
  author_id: 2
135
  content_type: application/octet-stream
test/fixtures/journal_details.yml
13 13
  value: "30"
14 14
  prop_key: done_ratio
15 15
  journal_id: 1
16
journal_details_003: 
17
  old_value: nil
18
  property: attr
19
  id: 3
20
  value: "6"
21
  prop_key: fixed_version_id
22
  journal_id: 4
test/fixtures/journals.yml
20 20
  journalized_type: Issue
21 21
  user_id: 2
22 22
  journalized_id: 2
23
  
23
journals_004: 
24
  created_on: <%= 1.days.ago.to_date.to_s(:db) %>
25
  notes: "A comment with a private version."
26
  id: 4
27
  journalized_type: Issue
28
  user_id: 1
29
  journalized_id: 6
30
    
test/fixtures/members.yml
30 30
  project_id: 5
31 31
  user_id: 2
32 32
  mail_notification: true
33
members_006: 
34
  created_on: 2006-07-19 19:35:33 +02:00
35
  project_id: 5
36
  id: 6
37
  user_id: 1
38
  mail_notification: true
33 39
  
test/fixtures/versions.yml
23 23
  id: 3
24 24
  description: Future version
25 25
  effective_date: 
26
  
26
versions_004: 
27
  created_on: 2006-07-19 21:00:33 +02:00
28
  name: "2.0"
29
  project_id: 3
30
  updated_on: 2006-07-19 21:00:33 +02:00
31
  id: 4
32
  description: Future version on subproject
33
  effective_date: 
34
versions_005: 
35
  created_on: 2006-07-19 21:00:07 +02:00
36
  name: "Alpha"
37
  project_id: 2
38
  updated_on: 2006-07-19 21:00:07 +02:00
39
  id: 5
40
  description: Private Alpha
41
  effective_date: 2006-07-01
42
versions_006: 
43
  created_on: 2006-07-19 21:00:07 +02:00
44
  name: "Private Version of public subproject"
45
  project_id: 5
46
  updated_on: 2006-07-19 21:00:07 +02:00
47
  id: 6
48
  description: "Should be done any day now..."
49
  effective_date: 
test/functional/issues_controller_test.rb
840 840
    assert_tag :input, :attributes => { :name => 'time_entry[hours]', :value => "2z" }
841 841
  end
842 842
  
843
  def test_post_edit_should_allow_fixed_version_to_be_set_to_a_subproject
844
    issue = Issue.find(2)
845
    @request.session[:user_id] = 2
846

  
847
    post :edit,
848
         :id => issue.id,
849
         :issue => {
850
           :fixed_version_id => 4
851
         }
852

  
853
    assert_response :redirect
854
    issue.reload
855
    assert_equal 4, issue.fixed_version_id
856
    assert_not_equal issue.project_id, issue.fixed_version.project_id
857
  end
858
  
843 859
  def test_get_bulk_edit
844 860
    @request.session[:user_id] = 2
845 861
    get :bulk_edit, :ids => [1, 2]
......
920 936
    assert_nil Issue.find(2).assigned_to
921 937
  end
922 938
  
939
  def test_post_bulk_edit_should_allow_fixed_version_to_be_set_to_a_subproject
940
    @request.session[:user_id] = 2
941

  
942
    post :bulk_edit,
943
         :ids => [1,2],
944
         :fixed_version_id => 4
945

  
946
    assert_response :redirect
947
    issues = Issue.find([1,2])
948
    issues.each do |issue|
949
      assert_equal 4, issue.fixed_version_id
950
      assert_not_equal issue.project_id, issue.fixed_version.project_id
951
    end
952
  end
953

  
923 954
  def test_move_routing
924 955
    assert_routing(
925 956
      {:method => :get, :path => '/issues/1/move'},
......
982 1013
    assert_tag :tag => 'a', :content => 'Immediate',
983 1014
                            :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;priority_id=8',
984 1015
                                             :class => '' }
1016
    # Versions
1017
    assert_tag :tag => 'a', :content => 'eCookbook - 0.1',
1018
                            :attributes => { :href => '/issues/bulk_edit?fixed_version_id=1&amp;ids%5B%5D=1',
1019
                                             :class => '' }
1020
    assert_tag :tag => 'a', :content => 'eCookbook - 1.0',
1021
                            :attributes => { :href => '/issues/bulk_edit?fixed_version_id=2&amp;ids%5B%5D=1',
1022
                                             :class => '' }
1023
    assert_tag :tag => 'a', :content => 'eCookbook Subproject 1 - 2.0',
1024
                            :attributes => { :href => '/issues/bulk_edit?fixed_version_id=4&amp;ids%5B%5D=1',
1025
                                             :class => '' }
1026

  
985 1027
    assert_tag :tag => 'a', :content => 'Dave Lopper',
986 1028
                            :attributes => { :href => '/issues/bulk_edit?assigned_to_id=3&amp;ids%5B%5D=1',
987 1029
                                             :class => '' }
test/functional/projects_controller_test.rb
316 316
                   :attributes => { :href => '/attachments/download/9/version_file.zip' }
317 317
  end
318 318

  
319
  def test_list_files_with_inherited_versions
320
    get :list_files, :id => 1
321
    assert_response :success
322
    assert_not_nil assigns(:containers)
323
    
324
    # file attached to a subproject's version
325
    assert_tag :a, :content => 'version_file.zip',
326
                   :attributes => { :href => '/attachments/download/11/version_file.zip' }
327
  end
328

  
319 329
  def test_list_files_routing
320 330
    assert_routing(
321 331
      {:method => :get, :path => '/projects/33/files'},
......
337 347
    assert_not_nil assigns(:versions)
338 348
  end
339 349
  
350
  def test_changelog_showing_inherited_versions
351
    get :changelog, :id => 1, :inherited_versions => 1
352
    assert_response :success
353
    assert_template 'changelog'
354
    assert_not_nil assigns(:versions)
355
    # Version on subproject appears
356
    assert assigns(:versions).include?(Version.find(4))
357
  end
358

  
340 359
  def test_roadmap_routing
341 360
    assert_routing(
342 361
      {:method => :get, :path => 'projects/33/roadmap'},
......
365 384
    # Completed version appears
366 385
    assert assigns(:versions).include?(Version.find(1))
367 386
  end
387

  
388
  def test_roadmap_showing_inherited_versions
389
    get :roadmap, :id => 1, :inherited_versions => 1
390
    assert_response :success
391
    assert_template 'roadmap'
392
    assert_not_nil assigns(:versions)
393
    # Version on subproject appears
394
    assert assigns(:versions).include?(Version.find(4))
395
  end
368 396
  
369 397
  def test_project_activity_routing
370 398
    assert_routing(
test/unit/helpers/application_helper_test.rb
32 32
  def setup
33 33
    super
34 34
  end
35

  
36
  def test_format_version_name_is_authorized
37
    User.current = User.find(1)
38
    assert_equal "eCookbook - 0.1", format_version_name(Version.find(1))
39
  end
40
  
41
  def test_format_version_name_is_unauthorized
42
    User.current = User.find(3)
43
    assert_equal "You are not authorized to view this.", format_version_name(Version.find(5))
44
  end
35 45
  
36 46
  def test_auto_links
37 47
    to_test = {
test/unit/helpers/projects_helper_test.rb
1
# Redmine - project management software
2
# Copyright (C) 2006-2009  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
# 
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
# 
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
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

  
18
require File.dirname(__FILE__) + '/../../test_helper'
19

  
20
class ProjectsHelperTest < HelperTestCase
21
  include ApplicationHelper
22
  include ProjectsHelper
23
  
24
  fixtures :all
25

  
26
  def setup
27
    super
28
    set_language_if_valid('en')
29
  end
30

  
31
  def test_link_to_version
32
    User.current = User.find(1)
33
    assert_equal '<a href="/versions/show/1">eCookbook - 0.1</a>', link_to_version(Version.find(1))
34
  end
35

  
36
  def test_link_to_version_invalid_version
37
    assert_equal '', link_to_version(Object)
38
  end
39

  
40
  def test_link_to_version_unauthorized
41
    User.current = User.find(3)
42
    assert_equal "You are not authorized to view this.", link_to_version(Version.find(5))
43
  end
44
end
test/unit/mailer_test.rb
238 238
    assert mail.bcc.include?('dlopper@somenet.foo')
239 239
    assert mail.body.include?('Bug #3: Error 281 when updating a recipe')
240 240
  end
241

  
242
  def test_issue_edit_should_not_show_private_version_changes_if_any_recipients_are_unauthorized
243
    Setting.default_language = 'en'
244
    # Move issue to a public project but with a Journal showing a
245
    # Private Version
246
    issue = Issue.find(6)
247
    issue.update_attribute(:project_id, 1)
248

  
249
    # User is allowed to see the Private Version
250
    User.current = User.find(1)
251
    # but another Member of Project #1 is not (dlopper@somenet.foo)
252

  
253
    journal = Journal.find(4)
254
    Mailer.deliver_issue_edit(journal)
255
    mail = ActionMailer::Base.deliveries.last
256
    
257
    assert !mail.body.include?('Private Version of public subproject'), "Private version exposed to unauthorized user"
258
    assert mail.body.include?('You are not authorized to view this.'), "Unauthorized message not displayed"
259
  end
241 260
end
test/unit/project_test.rb
21 21
  fixtures :projects, :enabled_modules, 
22 22
           :issues, :issue_statuses, :journals, :journal_details,
23 23
           :users, :members, :member_roles, :roles, :projects_trackers, :trackers, :boards,
24
           :queries
24
           :queries, :versions
25 25

  
26 26
  def setup
27 27
    @ecookbook = Project.find(1)
......
233 233
    
234 234
    assert_equal [1,2], parent.rolled_up_trackers.collect(&:id)
235 235
  end
236
  
236

  
237
  def test_inherited_versions
238
    parent = Project.find(1)
239
    child = parent.children.find(3)
240
    
241
    assert [1,2,3], parent.version_ids
242
    assert [4], child.version_ids
243

  
244
    assert_equal 5, parent.inherited_versions.size
245
    parent.inherited_versions.each do |version|
246
      assert_kind_of Version, version
247
    end
248

  
249
    assert_equal [1,2,3,4,6], parent.inherited_versions.collect(&:id)
250
  end
251

  
252
  def test_inherited_versions_should_ignore_archived_subprojects
253
    parent = Project.find(1)
254
    child = parent.children.find(3)
255
    child.archive
256
    parent.reload
257
    
258
    assert [1,2,3], parent.version_ids
259
    assert [4], child.version_ids
260
    assert !parent.inherited_versions.collect(&:id).include?(4)
261
  end
262

  
263
  def test_inherited_versions_visible_to_user
264
    user = User.find(3)
265
    parent = Project.find(1)
266
    child = parent.children.find(5)
267
    
268
    assert [1,2,3], parent.version_ids
269
    assert [6], child.version_ids
270

  
271
    versions = parent.inherited_versions_visible_to_user(user)
272
    
273
    assert_equal 4, versions.size
274
    versions.each do |version|
275
      assert_kind_of Version, version
276
    end
277

  
278
    assert !versions.collect(&:id).include?(6)
279
  end
280

  
237 281
  def test_next_identifier
238 282
    ProjectCustomField.delete_all
239 283
    Project.create!(:name => 'last', :identifier => 'p2008040')
test/unit/query_test.rb
31 31
      :include => [ :assigned_to, :status, :tracker, :project, :priority ], 
32 32
      :conditions => query.statement
33 33
  end
34

  
35
  def test_query_should_allow_inherited_versions_for_a_project_query
36
    subproject_version = Version.find(4)
37
    query = Query.new(:project => Project.find(1), :name => '_')
38
    query.add_filter('fixed_version_id', '=', [subproject_version.id.to_s])
39

  
40
    assert query.statement.include?("#{Issue.table_name}.fixed_version_id IN ('4')")
41
  end
34 42
  
35 43
  def test_query_with_multiple_custom_fields
36 44
    query = Query.find(1)