Restrict access for confidential issues on milestone view

parent 1029f410
...@@ -38,7 +38,7 @@ module MilestonesHelper ...@@ -38,7 +38,7 @@ module MilestonesHelper
def milestone_progress_bar(milestone) def milestone_progress_bar(milestone)
options = { options = {
class: 'progress-bar progress-bar-success', class: 'progress-bar progress-bar-success',
style: "width: #{milestone.percent_complete}%;" style: "width: #{milestone.percent_complete(current_user)}%;"
} }
content_tag :div, class: 'progress' do content_tag :div, class: 'progress' do
......
module Milestoneish module Milestoneish
def closed_items_count def closed_items_count(user = nil)
issues.closed.size + merge_requests.closed_and_merged.size issues_visible_to_user(user).closed.size + merge_requests.closed_and_merged.size
end end
def total_items_count def total_items_count(user = nil)
issues.size + merge_requests.size issues_visible_to_user(user).size + merge_requests.size
end end
def complete? def complete?(user = nil)
total_items_count == closed_items_count total_items_count(user) == closed_items_count(user)
end end
def percent_complete def percent_complete(user = nil)
((closed_items_count * 100) / total_items_count).abs ((closed_items_count(user) * 100) / total_items_count(user)).abs
rescue ZeroDivisionError rescue ZeroDivisionError
0 0
end end
...@@ -22,4 +22,8 @@ module Milestoneish ...@@ -22,4 +22,8 @@ module Milestoneish
(due_date - Date.today).to_i (due_date - Date.today).to_i
end end
def issues_visible_to_user(user = nil)
issues.visible_to_user(user)
end
end end
...@@ -121,8 +121,8 @@ class Milestone < ActiveRecord::Base ...@@ -121,8 +121,8 @@ class Milestone < ActiveRecord::Base
active? && issues.opened.count.zero? active? && issues.opened.count.zero?
end end
def is_empty? def is_empty?(user = nil)
total_items_count.zero? total_items_count(user).zero?
end end
def author_id def author_id
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
= preserve do = preserve do
= markdown @milestone.description = markdown @milestone.description
- if @milestone.complete? && @milestone.active? - if @milestone.complete?(current_user) && @milestone.active?
.alert.alert-success.prepend-top-default .alert.alert-success.prepend-top-default
%span All issues for this milestone are closed. You may close milestone now. %span All issues for this milestone are closed. You may close milestone now.
......
...@@ -6,10 +6,10 @@ ...@@ -6,10 +6,10 @@
.col-sm-6 .col-sm-6
%strong= link_to_gfm truncate(milestone.title, length: 100), milestone_path %strong= link_to_gfm truncate(milestone.title, length: 100), milestone_path
.col-sm-6 .col-sm-6
.pull-right.light #{milestone.percent_complete}% complete .pull-right.light #{milestone.percent_complete(current_user)}% complete
.row .row
.col-sm-6 .col-sm-6
= link_to pluralize(milestone.issues.size, 'Issue'), issues_path = link_to pluralize(milestone.issues_visible_to_user(current_user).size, 'Issue'), issues_path
&middot; &middot;
= link_to pluralize(milestone.merge_requests.size, 'Merge Request'), merge_requests_path = link_to pluralize(milestone.merge_requests.size, 'Merge Request'), merge_requests_path
.col-sm-6= milestone_progress_bar(milestone) .col-sm-6= milestone_progress_bar(milestone)
......
...@@ -3,15 +3,15 @@ ...@@ -3,15 +3,15 @@
.context.prepend-top-default .context.prepend-top-default
.milestone-summary .milestone-summary
%h4 Progress %h4 Progress
%strong= milestone.issues.size %strong= milestone.issues_visible_to_user(current_user).size
issues: issues:
%span.milestone-stat %span.milestone-stat
%strong= milestone.issues.opened.size %strong= milestone.issues_visible_to_user(current_user).opened.size
open and open and
%strong= milestone.issues.closed.size %strong= milestone.issues_visible_to_user(current_user).closed.size
closed closed
%span.milestone-stat %span.milestone-stat
%strong== #{milestone.percent_complete}% %strong== #{milestone.percent_complete(current_user)}%
complete complete
%span.milestone-stat %span.milestone-stat
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
%li.active %li.active
= link_to '#tab-issues', 'data-toggle' => 'tab', 'data-show' => '.tab-issues-buttons' do = link_to '#tab-issues', 'data-toggle' => 'tab', 'data-show' => '.tab-issues-buttons' do
Issues Issues
%span.badge= milestone.issues.size %span.badge= milestone.issues_visible_to_user(current_user).size
%li %li
= link_to '#tab-merge-requests', 'data-toggle' => 'tab', 'data-show' => '.tab-merge-requests-buttons' do = link_to '#tab-merge-requests', 'data-toggle' => 'tab', 'data-show' => '.tab-merge-requests-buttons' do
Merge Requests Merge Requests
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
.tab-content.milestone-content .tab-content.milestone-content
.tab-pane.active#tab-issues .tab-pane.active#tab-issues
= render 'shared/milestones/issues_tab', issues: milestone.issues, show_project_name: show_project_name, show_full_project_name: show_full_project_name = render 'shared/milestones/issues_tab', issues: milestone.issues_visible_to_user(current_user), show_project_name: show_project_name, show_full_project_name: show_full_project_name
.tab-pane#tab-merge-requests .tab-pane#tab-merge-requests
= render 'shared/milestones/merge_requests_tab', merge_requests: milestone.merge_requests, show_project_name: show_project_name, show_full_project_name: show_full_project_name = render 'shared/milestones/merge_requests_tab', merge_requests: milestone.merge_requests, show_project_name: show_project_name, show_full_project_name: show_full_project_name
.tab-pane#tab-participants .tab-pane#tab-participants
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
%h2.title %h2.title
= markdown escape_once(milestone.title), pipeline: :single_line = markdown escape_once(milestone.title), pipeline: :single_line
- if milestone.complete? && milestone.active? - if milestone.complete?(current_user) && milestone.active?
.alert.alert-success.prepend-top-default .alert.alert-success.prepend-top-default
- close_msg = group ? 'You may close the milestone now.' : 'Navigate to the project to close the milestone.' - close_msg = group ? 'You may close the milestone now.' : 'Navigate to the project to close the milestone.'
%span All issues for this milestone are closed. #{close_msg} %span All issues for this milestone are closed. #{close_msg}
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
- project_name = group ? ms.project.name : ms.project.name_with_namespace - project_name = group ? ms.project.name : ms.project.name_with_namespace
= link_to project_name, namespace_project_milestone_path(ms.project.namespace, ms.project, ms) = link_to project_name, namespace_project_milestone_path(ms.project.namespace, ms.project, ms)
%td %td
= ms.issues.opened.count = ms.issues_visible_to_user(current_user).opened.count
%td %td
- if ms.closed? - if ms.closed?
Closed Closed
......
require 'spec_helper'
describe Milestone, 'Milestoneish' do
let(:author) { create(:user) }
let(:assignee) { create(:user) }
let(:non_member) { create(:user) }
let(:member) { create(:user) }
let(:admin) { create(:admin) }
let(:project) { create(:project, :public) }
let(:milestone) { create(:milestone, project: project) }
let!(:issue) { create(:issue, project: project, milestone: milestone) }
let!(:security_issue_1) { create(:issue, :confidential, project: project, author: author, milestone: milestone) }
let!(:security_issue_2) { create(:issue, :confidential, project: project, assignee: assignee, milestone: milestone) }
let!(:closed_issue_1) { create(:issue, :closed, project: project, milestone: milestone) }
let!(:closed_issue_2) { create(:issue, :closed, project: project, milestone: milestone) }
let!(:closed_security_issue_1) { create(:issue, :confidential, :closed, project: project, author: author, milestone: milestone) }
let!(:closed_security_issue_2) { create(:issue, :confidential, :closed, project: project, assignee: assignee, milestone: milestone) }
let!(:closed_security_issue_3) { create(:issue, :confidential, :closed, project: project, author: author, milestone: milestone) }
let!(:closed_security_issue_4) { create(:issue, :confidential, :closed, project: project, assignee: assignee, milestone: milestone) }
let!(:merge_request) { create(:merge_request, source_project: project, target_project: project, milestone: milestone) }
before do
project.team << [member, :developer]
end
describe '#closed_items_count' do
it 'should not count confidential issues for non project members' do
expect(milestone.closed_items_count(non_member)).to eq 2
end
it 'should count confidential issues for author' do
expect(milestone.closed_items_count(author)).to eq 4
end
it 'should count confidential issues for assignee' do
expect(milestone.closed_items_count(assignee)).to eq 4
end
it 'should count confidential issues for project members' do
expect(milestone.closed_items_count(member)).to eq 6
end
it 'should count all issues for admin' do
expect(milestone.closed_items_count(admin)).to eq 6
end
end
describe '#total_items_count' do
it 'should not count confidential issues for non project members' do
expect(milestone.total_items_count(non_member)).to eq 4
end
it 'should count confidential issues for author' do
expect(milestone.total_items_count(author)).to eq 7
end
it 'should count confidential issues for assignee' do
expect(milestone.total_items_count(assignee)).to eq 7
end
it 'should count confidential issues for project members' do
expect(milestone.total_items_count(member)).to eq 10
end
it 'should count all issues for admin' do
expect(milestone.total_items_count(admin)).to eq 10
end
end
describe '#complete?' do
it 'returns false when has items opened' do
expect(milestone.complete?(non_member)).to eq false
end
it 'returns true when all items are closed' do
issue.close
merge_request.close
expect(milestone.complete?(non_member)).to eq true
end
end
describe '#percent_complete' do
it 'should not count confidential issues for non project members' do
expect(milestone.percent_complete(non_member)).to eq 50
end
it 'should count confidential issues for author' do
expect(milestone.percent_complete(author)).to eq 57
end
it 'should count confidential issues for assignee' do
expect(milestone.percent_complete(assignee)).to eq 57
end
it 'should count confidential issues for project members' do
expect(milestone.percent_complete(member)).to eq 60
end
it 'should count confidential issues for admin' do
expect(milestone.percent_complete(admin)).to eq 60
end
end
end
...@@ -32,6 +32,7 @@ describe Milestone, models: true do ...@@ -32,6 +32,7 @@ describe Milestone, models: true do
let(:milestone) { create(:milestone) } let(:milestone) { create(:milestone) }
let(:issue) { create(:issue) } let(:issue) { create(:issue) }
let(:user) { create(:user) }
describe "unique milestone title per project" do describe "unique milestone title per project" do
it "shouldn't accept the same title in a project twice" do it "shouldn't accept the same title in a project twice" do
...@@ -50,18 +51,17 @@ describe Milestone, models: true do ...@@ -50,18 +51,17 @@ describe Milestone, models: true do
describe "#percent_complete" do describe "#percent_complete" do
it "should not count open issues" do it "should not count open issues" do
milestone.issues << issue milestone.issues << issue
expect(milestone.percent_complete).to eq(0) expect(milestone.percent_complete(user)).to eq(0)
end end
it "should count closed issues" do it "should count closed issues" do
issue.close issue.close
milestone.issues << issue milestone.issues << issue
expect(milestone.percent_complete).to eq(100) expect(milestone.percent_complete(user)).to eq(100)
end end
it "should recover from dividing by zero" do it "should recover from dividing by zero" do
expect(milestone.issues).to receive(:size).and_return(0) expect(milestone.percent_complete(user)).to eq(0)
expect(milestone.percent_complete).to eq(0)
end end
end end
...@@ -103,7 +103,7 @@ describe Milestone, models: true do ...@@ -103,7 +103,7 @@ describe Milestone, models: true do
) )
end end
it { expect(milestone.percent_complete).to eq(75) } it { expect(milestone.percent_complete(user)).to eq(75) }
end end
describe :items_count do describe :items_count do
...@@ -113,23 +113,23 @@ describe Milestone, models: true do ...@@ -113,23 +113,23 @@ describe Milestone, models: true do
milestone.merge_requests << create(:merge_request) milestone.merge_requests << create(:merge_request)
end end
it { expect(milestone.closed_items_count).to eq(1) } it { expect(milestone.closed_items_count(user)).to eq(1) }
it { expect(milestone.total_items_count).to eq(3) } it { expect(milestone.total_items_count(user)).to eq(3) }
it { expect(milestone.is_empty?).to be_falsey } it { expect(milestone.is_empty?(user)).to be_falsey }
end end
describe :can_be_closed? do describe :can_be_closed? do
it { expect(milestone.can_be_closed?).to be_truthy } it { expect(milestone.can_be_closed?).to be_truthy }
end end
describe :is_empty? do describe :total_items_count do
before do before do
create :closed_issue, milestone: milestone create :closed_issue, milestone: milestone
create :merge_request, milestone: milestone create :merge_request, milestone: milestone
end end
it 'Should return total count of issues and merge requests assigned to milestone' do it 'Should return total count of issues and merge requests assigned to milestone' do
expect(milestone.total_items_count).to eq 2 expect(milestone.total_items_count(user)).to eq 2
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment