Project members with guest role can't access confidential issues
This commit is contained in:
		
							parent
							
								
									af8500f430
								
							
						
					
					
						commit
						b56c456750
					
				|  | @ -51,7 +51,7 @@ class SnippetsFinder | |||
|     snippets = project.snippets.fresh | ||||
| 
 | ||||
|     if current_user | ||||
|       if project.team.member?(current_user.id) || current_user.admin? | ||||
|       if project.team.member?(current_user) || current_user.admin? | ||||
|         snippets | ||||
|       else | ||||
|         snippets.public_and_internal | ||||
|  |  | |||
|  | @ -533,7 +533,7 @@ class Ability | |||
|     def filter_confidential_issues_abilities(user, issue, rules) | ||||
|       return rules if user.admin? || !issue.confidential? | ||||
| 
 | ||||
|       unless issue.author == user || issue.assignee == user || issue.project.team.member?(user.id) | ||||
|       unless issue.author == user || issue.assignee == user || issue.project.team.member?(user, Gitlab::Access::REPORTER) | ||||
|         rules.delete(:admin_issue) | ||||
|         rules.delete(:read_issue) | ||||
|         rules.delete(:update_issue) | ||||
|  |  | |||
|  | @ -54,7 +54,15 @@ class Issue < ActiveRecord::Base | |||
|     return where(confidential: false) if user.blank? | ||||
|     return all if user.admin? | ||||
| 
 | ||||
|     where('issues.confidential = false OR (issues.confidential = true AND (issues.author_id = :user_id OR issues.assignee_id = :user_id OR issues.project_id IN(:project_ids)))', user_id: user.id, project_ids: user.authorized_projects.select(:id)) | ||||
|     where(' | ||||
|       issues.confidential IS NULL | ||||
|       OR issues.confidential IS FALSE | ||||
|       OR (issues.confidential = TRUE | ||||
|         AND (issues.author_id = :user_id | ||||
|           OR issues.assignee_id = :user_id | ||||
|           OR issues.project_id IN(:project_ids)))', | ||||
|       user_id: user.id, | ||||
|       project_ids: user.authorized_projects(Gitlab::Access::REPORTER).select(:id)) | ||||
|   end | ||||
| 
 | ||||
|   def self.reference_prefix | ||||
|  |  | |||
|  | @ -100,7 +100,7 @@ class Note < ActiveRecord::Base | |||
|             OR issues.assignee_id = :user_id | ||||
|             OR issues.project_id IN(:project_ids)))', | ||||
|           user_id: as_user.id, | ||||
|           project_ids: as_user.authorized_projects.select(:id)) | ||||
|           project_ids: as_user.authorized_projects(Gitlab::Access::REPORTER).select(:id)) | ||||
|       else | ||||
|         found_notes.where('issues.confidential IS NULL OR issues.confidential IS FALSE') | ||||
|       end | ||||
|  |  | |||
|  | @ -131,8 +131,14 @@ class ProjectTeam | |||
|     max_member_access(user.id) == Gitlab::Access::MASTER | ||||
|   end | ||||
| 
 | ||||
|   def member?(user_id) | ||||
|     !!find_member(user_id) | ||||
|   def member?(user, min_member_access = nil) | ||||
|     member = !!find_member(user.id) | ||||
| 
 | ||||
|     if min_member_access | ||||
|       member && max_member_access(user.id) >= min_member_access | ||||
|     else | ||||
|       member | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def human_max_access(user_id) | ||||
|  |  | |||
|  | @ -405,8 +405,8 @@ class User < ActiveRecord::Base | |||
|   end | ||||
| 
 | ||||
|   # Returns projects user is authorized to access. | ||||
|   def authorized_projects | ||||
|     Project.where("projects.id IN (#{projects_union.to_sql})") | ||||
|   def authorized_projects(min_access_level = nil) | ||||
|     Project.where("projects.id IN (#{projects_union(min_access_level).to_sql})") | ||||
|   end | ||||
| 
 | ||||
|   def viewable_starred_projects | ||||
|  | @ -824,11 +824,22 @@ class User < ActiveRecord::Base | |||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def projects_union | ||||
|     Gitlab::SQL::Union.new([personal_projects.select(:id), | ||||
|   def projects_union(min_access_level = nil) | ||||
|     relations = if min_access_level | ||||
|                   scope = { access_level: Gitlab::Access.values.select { |access| access >= min_access_level } } | ||||
| 
 | ||||
|                   [personal_projects.select(:id), | ||||
|                    groups_projects.where(members: scope).select(:id), | ||||
|                    projects.where(members: scope).select(:id), | ||||
|                    groups.joins(:shared_projects).where(members: scope).select(:project_id)] | ||||
|                 else | ||||
|                   [personal_projects.select(:id), | ||||
|                    groups_projects.select(:id), | ||||
|                    projects.select(:id), | ||||
|                             groups.joins(:shared_projects).select(:project_id)]) | ||||
|                    groups.joins(:shared_projects).select(:project_id)] | ||||
|                 end | ||||
| 
 | ||||
|     Gitlab::SQL::Union.new(relations) | ||||
|   end | ||||
| 
 | ||||
|   def ci_projects_union | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ | |||
|       .checkbox | ||||
|         = f.label :confidential do | ||||
|           = f.check_box :confidential | ||||
|           This issue is confidential and should only be visible to team members | ||||
|           This issue is confidential and should only be visible to team members with at least Reporter access. | ||||
| 
 | ||||
| - if can?(current_user, :"admin_#{issuable.to_ability_name}", issuable.project) | ||||
|   - has_due_date = issuable.has_attribute?(:due_date) | ||||
|  |  | |||
|  | @ -105,6 +105,15 @@ describe Projects::IssuesController do | |||
|         expect(assigns(:issues)).to eq [issue] | ||||
|       end | ||||
| 
 | ||||
|       it 'should not list confidential issues for project members with guest role' do | ||||
|         sign_in(member) | ||||
|         project.team << [member, :guest] | ||||
| 
 | ||||
|         get_issues | ||||
| 
 | ||||
|         expect(assigns(:issues)).to eq [issue] | ||||
|       end | ||||
| 
 | ||||
|       it 'should list confidential issues for author' do | ||||
|         sign_in(author) | ||||
|         get_issues | ||||
|  | @ -148,7 +157,7 @@ describe Projects::IssuesController do | |||
| 
 | ||||
|     shared_examples_for 'restricted action' do |http_status| | ||||
|       it 'returns 404 for guests' do | ||||
|         sign_out :user | ||||
|         sign_out(:user) | ||||
|         go(id: unescaped_parameter_value.to_param) | ||||
| 
 | ||||
|         expect(response).to have_http_status :not_found | ||||
|  | @ -161,6 +170,14 @@ describe Projects::IssuesController do | |||
|         expect(response).to have_http_status :not_found | ||||
|       end | ||||
| 
 | ||||
|       it 'returns 404 for project members with guest role' do | ||||
|         sign_in(member) | ||||
|         project.team << [member, :guest] | ||||
|         go(id: unescaped_parameter_value.to_param) | ||||
| 
 | ||||
|         expect(response).to have_http_status :not_found | ||||
|       end | ||||
| 
 | ||||
|       it "returns #{http_status[:success]} for author" do | ||||
|         sign_in(author) | ||||
|         go(id: unescaped_parameter_value.to_param) | ||||
|  |  | |||
|  | @ -69,6 +69,18 @@ describe Banzai::Filter::RedactorFilter, lib: true do | |||
|         expect(doc.css('a').length).to eq 0 | ||||
|       end | ||||
| 
 | ||||
|       it 'removes references for project members with guest role' do | ||||
|         member = create(:user) | ||||
|         project = create(:empty_project, :public) | ||||
|         project.team << [member, :guest] | ||||
|         issue = create(:issue, :confidential, project: project) | ||||
| 
 | ||||
|         link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue') | ||||
|         doc = filter(link, current_user: member) | ||||
| 
 | ||||
|         expect(doc.css('a').length).to eq 0 | ||||
|       end | ||||
| 
 | ||||
|       it 'allows references for author' do | ||||
|         author = create(:user) | ||||
|         project = create(:empty_project, :public) | ||||
|  |  | |||
|  | @ -43,6 +43,18 @@ describe Gitlab::ProjectSearchResults, lib: true do | |||
|       expect(results.issues_count).to eq 1 | ||||
|     end | ||||
| 
 | ||||
|     it 'should not list project confidential issues for project members with guest role' do | ||||
|       project.team << [member, :guest] | ||||
| 
 | ||||
|       results = described_class.new(member, project, query) | ||||
|       issues = results.objects('issues') | ||||
| 
 | ||||
|       expect(issues).to include issue | ||||
|       expect(issues).not_to include security_issue_1 | ||||
|       expect(issues).not_to include security_issue_2 | ||||
|       expect(results.issues_count).to eq 1 | ||||
|     end | ||||
| 
 | ||||
|     it 'should list project confidential issues for author' do | ||||
|       results = described_class.new(author, project, query) | ||||
|       issues = results.objects('issues') | ||||
|  |  | |||
|  | @ -86,6 +86,22 @@ describe Gitlab::SearchResults do | |||
|       expect(results.issues_count).to eq 1 | ||||
|     end | ||||
| 
 | ||||
|     it 'should not list confidential issues for project members with guest role' do | ||||
|       project_1.team << [member, :guest] | ||||
|       project_2.team << [member, :guest] | ||||
| 
 | ||||
|       results = described_class.new(member, limit_projects, query) | ||||
|       issues = results.objects('issues') | ||||
| 
 | ||||
|       expect(issues).to include issue | ||||
|       expect(issues).not_to include security_issue_1 | ||||
|       expect(issues).not_to include security_issue_2 | ||||
|       expect(issues).not_to include security_issue_3 | ||||
|       expect(issues).not_to include security_issue_4 | ||||
|       expect(issues).not_to include security_issue_5 | ||||
|       expect(results.issues_count).to eq 1 | ||||
|     end | ||||
| 
 | ||||
|     it 'should list confidential issues for author' do | ||||
|       results = described_class.new(author, limit_projects, query) | ||||
|       issues = results.objects('issues') | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ describe Milestone, 'Milestoneish' do | |||
|   let(:assignee) { create(:user) } | ||||
|   let(:non_member) { create(:user) } | ||||
|   let(:member) { create(:user) } | ||||
|   let(:guest) { create(:user) } | ||||
|   let(:admin) { create(:admin) } | ||||
|   let(:project) { create(:project, :public) } | ||||
|   let(:milestone) { create(:milestone, project: project) } | ||||
|  | @ -21,6 +22,7 @@ describe Milestone, 'Milestoneish' do | |||
| 
 | ||||
|   before do | ||||
|     project.team << [member, :developer] | ||||
|     project.team << [guest, :guest] | ||||
|   end | ||||
| 
 | ||||
|   describe '#closed_items_count' do | ||||
|  | @ -28,6 +30,10 @@ describe Milestone, 'Milestoneish' do | |||
|       expect(milestone.closed_items_count(non_member)).to eq 2 | ||||
|     end | ||||
| 
 | ||||
|     it 'should not count confidential issues for project members with guest role' do | ||||
|       expect(milestone.closed_items_count(guest)).to eq 2 | ||||
|     end | ||||
| 
 | ||||
|     it 'should count confidential issues for author' do | ||||
|       expect(milestone.closed_items_count(author)).to eq 4 | ||||
|     end | ||||
|  | @ -50,6 +56,10 @@ describe Milestone, 'Milestoneish' do | |||
|       expect(milestone.total_items_count(non_member)).to eq 4 | ||||
|     end | ||||
| 
 | ||||
|     it 'should not count confidential issues for project members with guest role' do | ||||
|       expect(milestone.total_items_count(guest)).to eq 4 | ||||
|     end | ||||
| 
 | ||||
|     it 'should count confidential issues for author' do | ||||
|       expect(milestone.total_items_count(author)).to eq 7 | ||||
|     end | ||||
|  | @ -85,6 +95,10 @@ describe Milestone, 'Milestoneish' do | |||
|       expect(milestone.percent_complete(non_member)).to eq 50 | ||||
|     end | ||||
| 
 | ||||
|     it 'should not count confidential issues for project members with guest role' do | ||||
|       expect(milestone.percent_complete(guest)).to eq 50 | ||||
|     end | ||||
| 
 | ||||
|     it 'should count confidential issues for author' do | ||||
|       expect(milestone.percent_complete(author)).to eq 57 | ||||
|     end | ||||
|  |  | |||
|  | @ -50,6 +50,7 @@ describe Event, models: true do | |||
|     let(:project) { create(:empty_project, :public) } | ||||
|     let(:non_member) { create(:user) } | ||||
|     let(:member)  { create(:user) } | ||||
|     let(:guest)  { create(:user) } | ||||
|     let(:author) { create(:author) } | ||||
|     let(:assignee) { create(:user) } | ||||
|     let(:admin) { create(:admin) } | ||||
|  | @ -61,6 +62,7 @@ describe Event, models: true do | |||
| 
 | ||||
|     before do | ||||
|       project.team << [member, :developer] | ||||
|       project.team << [guest, :guest] | ||||
|     end | ||||
| 
 | ||||
|     context 'issue event' do | ||||
|  | @ -71,6 +73,7 @@ describe Event, models: true do | |||
|         it { expect(event.visible_to_user?(author)).to eq true } | ||||
|         it { expect(event.visible_to_user?(assignee)).to eq true } | ||||
|         it { expect(event.visible_to_user?(member)).to eq true } | ||||
|         it { expect(event.visible_to_user?(guest)).to eq true } | ||||
|         it { expect(event.visible_to_user?(admin)).to eq true } | ||||
|       end | ||||
| 
 | ||||
|  | @ -81,6 +84,7 @@ describe Event, models: true do | |||
|         it { expect(event.visible_to_user?(author)).to eq true } | ||||
|         it { expect(event.visible_to_user?(assignee)).to eq true } | ||||
|         it { expect(event.visible_to_user?(member)).to eq true } | ||||
|         it { expect(event.visible_to_user?(guest)).to eq false } | ||||
|         it { expect(event.visible_to_user?(admin)).to eq true } | ||||
|       end | ||||
|     end | ||||
|  | @ -93,6 +97,7 @@ describe Event, models: true do | |||
|         it { expect(event.visible_to_user?(author)).to eq true } | ||||
|         it { expect(event.visible_to_user?(assignee)).to eq true } | ||||
|         it { expect(event.visible_to_user?(member)).to eq true } | ||||
|         it { expect(event.visible_to_user?(guest)).to eq true } | ||||
|         it { expect(event.visible_to_user?(admin)).to eq true } | ||||
|       end | ||||
| 
 | ||||
|  | @ -103,6 +108,7 @@ describe Event, models: true do | |||
|         it { expect(event.visible_to_user?(author)).to eq true } | ||||
|         it { expect(event.visible_to_user?(assignee)).to eq true } | ||||
|         it { expect(event.visible_to_user?(member)).to eq true } | ||||
|         it { expect(event.visible_to_user?(guest)).to eq false } | ||||
|         it { expect(event.visible_to_user?(admin)).to eq true } | ||||
|       end | ||||
|     end | ||||
|  |  | |||
|  | @ -162,16 +162,23 @@ describe Note, models: true do | |||
|     end | ||||
| 
 | ||||
|     context "confidential issues" do | ||||
|       let(:user) { create :user } | ||||
|       let(:confidential_issue) { create(:issue, :confidential, author: user) } | ||||
|       let(:confidential_note) { create :note, note: "Random", noteable: confidential_issue, project: confidential_issue.project } | ||||
|       let(:user) { create(:user) } | ||||
|       let(:project) { create(:project) } | ||||
|       let(:confidential_issue) { create(:issue, :confidential, project: project, author: user) } | ||||
|       let(:confidential_note) { create(:note, note: "Random", noteable: confidential_issue, project: confidential_issue.project) } | ||||
| 
 | ||||
|       it "returns notes with matching content if user can see the issue" do | ||||
|         expect(described_class.search(confidential_note.note, as_user: user)).to eq([confidential_note]) | ||||
|       end | ||||
| 
 | ||||
|       it "does not return notes with matching content if user can not see the issue" do | ||||
|         user = create :user | ||||
|         user = create(:user) | ||||
|         expect(described_class.search(confidential_note.note, as_user: user)).to be_empty | ||||
|       end | ||||
| 
 | ||||
|       it "does not return notes with matching content for project members with guest role" do | ||||
|         user = create(:user) | ||||
|         project.team << [user, :guest] | ||||
|         expect(described_class.search(confidential_note.note, as_user: user)).to be_empty | ||||
|       end | ||||
| 
 | ||||
|  |  | |||
|  | @ -29,6 +29,9 @@ describe ProjectTeam, models: true do | |||
|       it { expect(project.team.master?(nonmember)).to be_falsey } | ||||
|       it { expect(project.team.member?(nonmember)).to be_falsey } | ||||
|       it { expect(project.team.member?(guest)).to be_truthy } | ||||
|       it { expect(project.team.member?(reporter, Gitlab::Access::REPORTER)).to be_truthy } | ||||
|       it { expect(project.team.member?(guest, Gitlab::Access::REPORTER)).to be_falsey } | ||||
|       it { expect(project.team.member?(nonmember, Gitlab::Access::GUEST)).to be_falsey } | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|  | @ -64,6 +67,9 @@ describe ProjectTeam, models: true do | |||
|       it { expect(project.team.master?(nonmember)).to be_falsey } | ||||
|       it { expect(project.team.member?(nonmember)).to be_falsey } | ||||
|       it { expect(project.team.member?(guest)).to be_truthy } | ||||
|       it { expect(project.team.member?(guest, Gitlab::Access::MASTER)).to be_truthy } | ||||
|       it { expect(project.team.member?(reporter, Gitlab::Access::MASTER)).to be_falsey } | ||||
|       it { expect(project.team.member?(nonmember, Gitlab::Access::GUEST)).to be_falsey } | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ describe API::API, api: true  do | |||
|   let(:user)        { create(:user) } | ||||
|   let(:user2)       { create(:user) } | ||||
|   let(:non_member)  { create(:user) } | ||||
|   let(:guest)       { create(:user) } | ||||
|   let(:author)      { create(:author) } | ||||
|   let(:assignee)    { create(:assignee) } | ||||
|   let(:admin)       { create(:user, :admin) } | ||||
|  | @ -41,7 +42,10 @@ describe API::API, api: true  do | |||
|   end | ||||
|   let!(:note) { create(:note_on_issue, author: user, project: project, noteable: issue) } | ||||
| 
 | ||||
|   before { project.team << [user, :reporter] } | ||||
|   before do | ||||
|     project.team << [user, :reporter] | ||||
|     project.team << [guest, :guest] | ||||
|   end | ||||
| 
 | ||||
|   describe "GET /issues" do | ||||
|     context "when unauthenticated" do | ||||
|  | @ -144,6 +148,14 @@ describe API::API, api: true  do | |||
|       expect(json_response.first['title']).to eq(issue.title) | ||||
|     end | ||||
| 
 | ||||
|     it 'should return project issues without confidential issues for project members with guest role' do | ||||
|       get api("#{base_url}/issues", guest) | ||||
|       expect(response.status).to eq(200) | ||||
|       expect(json_response).to be_an Array | ||||
|       expect(json_response.length).to eq(2) | ||||
|       expect(json_response.first['title']).to eq(issue.title) | ||||
|     end | ||||
| 
 | ||||
|     it 'should return project confidential issues for author' do | ||||
|       get api("#{base_url}/issues", author) | ||||
|       expect(response.status).to eq(200) | ||||
|  | @ -278,6 +290,11 @@ describe API::API, api: true  do | |||
|         expect(response.status).to eq(404) | ||||
|       end | ||||
| 
 | ||||
|       it "should return 404 for project members with guest role" do | ||||
|         get api("/projects/#{project.id}/issues/#{confidential_issue.id}", guest) | ||||
|         expect(response.status).to eq(404) | ||||
|       end | ||||
| 
 | ||||
|       it "should return confidential issue for project members" do | ||||
|         get api("/projects/#{project.id}/issues/#{confidential_issue.id}", user) | ||||
|         expect(response.status).to eq(200) | ||||
|  | @ -413,6 +430,12 @@ describe API::API, api: true  do | |||
|         expect(response.status).to eq(403) | ||||
|       end | ||||
| 
 | ||||
|       it "should return 403 for project members with guest role" do | ||||
|         put api("/projects/#{project.id}/issues/#{confidential_issue.id}", guest), | ||||
|           title: 'updated title' | ||||
|         expect(response.status).to eq(403) | ||||
|       end | ||||
| 
 | ||||
|       it "should update a confidential issue for project members" do | ||||
|         put api("/projects/#{project.id}/issues/#{confidential_issue.id}", user), | ||||
|           title: 'updated title' | ||||
|  |  | |||
|  | @ -146,6 +146,7 @@ describe API::API, api: true  do | |||
|       let(:milestone) { create(:milestone, project: public_project) } | ||||
|       let(:issue) { create(:issue, project: public_project) } | ||||
|       let(:confidential_issue) { create(:issue, confidential: true, project: public_project) } | ||||
| 
 | ||||
|       before do | ||||
|         public_project.team << [user, :developer] | ||||
|         milestone.issues << issue << confidential_issue | ||||
|  | @ -160,6 +161,18 @@ describe API::API, api: true  do | |||
|         expect(json_response.map { |issue| issue['id'] }).to include(issue.id, confidential_issue.id) | ||||
|       end | ||||
| 
 | ||||
|       it 'does not return confidential issues to team members with guest role' do | ||||
|         member = create(:user) | ||||
|         project.team << [member, :guest] | ||||
| 
 | ||||
|         get api("/projects/#{public_project.id}/milestones/#{milestone.id}/issues", member) | ||||
| 
 | ||||
|         expect(response.status).to eq(200) | ||||
|         expect(json_response).to be_an Array | ||||
|         expect(json_response.size).to eq(1) | ||||
|         expect(json_response.map { |issue| issue['id'] }).to include(issue.id) | ||||
|       end | ||||
| 
 | ||||
|       it 'does not return confidential issues to regular users' do | ||||
|         get api("/projects/#{public_project.id}/milestones/#{milestone.id}/issues", create(:user)) | ||||
| 
 | ||||
|  |  | |||
|  | @ -132,12 +132,14 @@ describe NotificationService, services: true do | |||
|       let(:assignee) { create(:user) } | ||||
|       let(:non_member) { create(:user) } | ||||
|       let(:member) { create(:user) } | ||||
|       let(:guest) { create(:user) } | ||||
|       let(:admin) { create(:admin) } | ||||
|       let(:confidential_issue) { create(:issue, :confidential, project: project, author: author, assignee: assignee) } | ||||
|       let(:note) { create(:note_on_issue, noteable: confidential_issue, project: project, note: "#{author.to_reference} #{assignee.to_reference} #{non_member.to_reference} #{member.to_reference} #{admin.to_reference}") } | ||||
| 
 | ||||
|       it 'filters out users that can not read the issue' do | ||||
|         project.team << [member, :developer] | ||||
|         project.team << [guest, :guest] | ||||
| 
 | ||||
|         expect(SentNotification).to receive(:record).with(confidential_issue, any_args).exactly(4).times | ||||
| 
 | ||||
|  | @ -146,6 +148,7 @@ describe NotificationService, services: true do | |||
|         notification.new_note(note) | ||||
| 
 | ||||
|         should_not_email(non_member) | ||||
|         should_not_email(guest) | ||||
|         should_email(author) | ||||
|         should_email(assignee) | ||||
|         should_email(member) | ||||
|  | @ -322,17 +325,20 @@ describe NotificationService, services: true do | |||
|         let(:assignee) { create(:user) } | ||||
|         let(:non_member) { create(:user) } | ||||
|         let(:member) { create(:user) } | ||||
|         let(:guest) { create(:user) } | ||||
|         let(:admin) { create(:admin) } | ||||
|         let(:confidential_issue) { create(:issue, :confidential, project: project, title: 'Confidential issue', author: author, assignee: assignee) } | ||||
| 
 | ||||
|         it "emails subscribers of the issue's labels that can read the issue" do | ||||
|           project.team << [member, :developer] | ||||
|           project.team << [guest, :guest] | ||||
| 
 | ||||
|           label = create(:label, issues: [confidential_issue]) | ||||
|           label.toggle_subscription(non_member) | ||||
|           label.toggle_subscription(author) | ||||
|           label.toggle_subscription(assignee) | ||||
|           label.toggle_subscription(member) | ||||
|           label.toggle_subscription(guest) | ||||
|           label.toggle_subscription(admin) | ||||
| 
 | ||||
|           ActionMailer::Base.deliveries.clear | ||||
|  | @ -341,6 +347,7 @@ describe NotificationService, services: true do | |||
| 
 | ||||
|           should_not_email(non_member) | ||||
|           should_not_email(author) | ||||
|           should_not_email(guest) | ||||
|           should_email(assignee) | ||||
|           should_email(member) | ||||
|           should_email(admin) | ||||
|  | @ -490,6 +497,7 @@ describe NotificationService, services: true do | |||
|         let(:assignee) { create(:user) } | ||||
|         let(:non_member) { create(:user) } | ||||
|         let(:member) { create(:user) } | ||||
|         let(:guest) { create(:user) } | ||||
|         let(:admin) { create(:admin) } | ||||
|         let(:confidential_issue) { create(:issue, :confidential, project: project, title: 'Confidential issue', author: author, assignee: assignee) } | ||||
|         let!(:label_1) { create(:label, issues: [confidential_issue]) } | ||||
|  | @ -497,11 +505,13 @@ describe NotificationService, services: true do | |||
| 
 | ||||
|         it "emails subscribers of the issue's labels that can read the issue" do | ||||
|           project.team << [member, :developer] | ||||
|           project.team << [guest, :guest] | ||||
| 
 | ||||
|           label_2.toggle_subscription(non_member) | ||||
|           label_2.toggle_subscription(author) | ||||
|           label_2.toggle_subscription(assignee) | ||||
|           label_2.toggle_subscription(member) | ||||
|           label_2.toggle_subscription(guest) | ||||
|           label_2.toggle_subscription(admin) | ||||
| 
 | ||||
|           ActionMailer::Base.deliveries.clear | ||||
|  | @ -509,6 +519,7 @@ describe NotificationService, services: true do | |||
|           notification.relabeled_issue(confidential_issue, [label_2], @u_disabled) | ||||
| 
 | ||||
|           should_not_email(non_member) | ||||
|           should_not_email(guest) | ||||
|           should_email(author) | ||||
|           should_email(assignee) | ||||
|           should_email(member) | ||||
|  |  | |||
|  | @ -33,6 +33,18 @@ describe Projects::AutocompleteService, services: true do | |||
|         expect(issues.count).to eq 1 | ||||
|       end | ||||
| 
 | ||||
|       it 'should not list project confidential issues for project members with guest role' do | ||||
|         project.team << [member, :guest] | ||||
| 
 | ||||
|         autocomplete = described_class.new(project, non_member) | ||||
|         issues = autocomplete.issues.map(&:iid) | ||||
| 
 | ||||
|         expect(issues).to include issue.iid | ||||
|         expect(issues).not_to include security_issue_1.iid | ||||
|         expect(issues).not_to include security_issue_2.iid | ||||
|         expect(issues.count).to eq 1 | ||||
|       end | ||||
| 
 | ||||
|       it 'should list project confidential issues for author' do | ||||
|         autocomplete = described_class.new(project, author) | ||||
|         issues = autocomplete.issues.map(&:iid) | ||||
|  |  | |||
|  | @ -5,13 +5,15 @@ describe TodoService, services: true do | |||
|   let(:assignee) { create(:user) } | ||||
|   let(:non_member) { create(:user) } | ||||
|   let(:member) { create(:user) } | ||||
|   let(:guest) { create(:user) } | ||||
|   let(:admin) { create(:admin) } | ||||
|   let(:john_doe) { create(:user) } | ||||
|   let(:project) { create(:project) } | ||||
|   let(:mentions) { [author, assignee, john_doe, member, non_member, admin].map(&:to_reference).join(' ') } | ||||
|   let(:mentions) { [author, assignee, john_doe, member, guest, non_member, admin].map(&:to_reference).join(' ') } | ||||
|   let(:service) { described_class.new } | ||||
| 
 | ||||
|   before do | ||||
|     project.team << [guest, :guest] | ||||
|     project.team << [author, :developer] | ||||
|     project.team << [member, :developer] | ||||
|     project.team << [john_doe, :developer] | ||||
|  | @ -41,18 +43,20 @@ describe TodoService, services: true do | |||
|         service.new_issue(issue, author) | ||||
| 
 | ||||
|         should_create_todo(user: member, target: issue, action: Todo::MENTIONED) | ||||
|         should_create_todo(user: guest, target: issue, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: author, target: issue, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: john_doe, target: issue, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: non_member, target: issue, action: Todo::MENTIONED) | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create todo for non project members when issue is confidential' do | ||||
|       it 'does not create todo if user can not see the issue when issue is confidential' do | ||||
|         service.new_issue(confidential_issue, john_doe) | ||||
| 
 | ||||
|         should_create_todo(user: assignee, target: confidential_issue, author: john_doe, action: Todo::ASSIGNED) | ||||
|         should_create_todo(user: author, target: confidential_issue, author: john_doe, action: Todo::MENTIONED) | ||||
|         should_create_todo(user: member, target: confidential_issue, author: john_doe, action: Todo::MENTIONED) | ||||
|         should_create_todo(user: admin, target: confidential_issue, author: john_doe, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: guest, target: confidential_issue, author: john_doe, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: john_doe, target: confidential_issue, author: john_doe, action: Todo::MENTIONED) | ||||
|       end | ||||
| 
 | ||||
|  | @ -81,6 +85,7 @@ describe TodoService, services: true do | |||
|         service.update_issue(issue, author) | ||||
| 
 | ||||
|         should_create_todo(user: member, target: issue, action: Todo::MENTIONED) | ||||
|         should_create_todo(user: guest, target: issue, action: Todo::MENTIONED) | ||||
|         should_create_todo(user: john_doe, target: issue, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: author, target: issue, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: non_member, target: issue, action: Todo::MENTIONED) | ||||
|  | @ -92,13 +97,14 @@ describe TodoService, services: true do | |||
|         expect { service.update_issue(issue, author) }.not_to change(member.todos, :count) | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create todo for non project members when issue is confidential' do | ||||
|       it 'does not create todo if user can not see the issue when issue is confidential' do | ||||
|         service.update_issue(confidential_issue, john_doe) | ||||
| 
 | ||||
|         should_create_todo(user: author, target: confidential_issue, author: john_doe, action: Todo::MENTIONED) | ||||
|         should_create_todo(user: assignee, target: confidential_issue, author: john_doe, action: Todo::MENTIONED) | ||||
|         should_create_todo(user: member, target: confidential_issue, author: john_doe, action: Todo::MENTIONED) | ||||
|         should_create_todo(user: admin, target: confidential_issue, author: john_doe, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: guest, target: confidential_issue, author: john_doe, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: john_doe, target: confidential_issue, author: john_doe, action: Todo::MENTIONED) | ||||
|       end | ||||
| 
 | ||||
|  | @ -192,18 +198,20 @@ describe TodoService, services: true do | |||
|         service.new_note(note, john_doe) | ||||
| 
 | ||||
|         should_create_todo(user: member, target: issue, author: john_doe, action: Todo::MENTIONED, note: note) | ||||
|         should_create_todo(user: guest, target: issue, author: john_doe, action: Todo::MENTIONED, note: note) | ||||
|         should_create_todo(user: author, target: issue, author: john_doe, action: Todo::MENTIONED, note: note) | ||||
|         should_not_create_todo(user: john_doe, target: issue, author: john_doe, action: Todo::MENTIONED, note: note) | ||||
|         should_not_create_todo(user: non_member, target: issue, author: john_doe, action: Todo::MENTIONED, note: note) | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create todo for non project members when leaving a note on a confidential issue' do | ||||
|       it 'does not create todo if user can not see the issue when leaving a note on a confidential issue' do | ||||
|         service.new_note(note_on_confidential_issue, john_doe) | ||||
| 
 | ||||
|         should_create_todo(user: author, target: confidential_issue, author: john_doe, action: Todo::MENTIONED, note: note_on_confidential_issue) | ||||
|         should_create_todo(user: assignee, target: confidential_issue, author: john_doe, action: Todo::MENTIONED, note: note_on_confidential_issue) | ||||
|         should_create_todo(user: member, target: confidential_issue, author: john_doe, action: Todo::MENTIONED, note: note_on_confidential_issue) | ||||
|         should_create_todo(user: admin, target: confidential_issue, author: john_doe, action: Todo::MENTIONED, note: note_on_confidential_issue) | ||||
|         should_not_create_todo(user: guest, target: confidential_issue, author: john_doe, action: Todo::MENTIONED, note: note_on_confidential_issue) | ||||
|         should_not_create_todo(user: john_doe, target: confidential_issue, author: john_doe, action: Todo::MENTIONED, note: note_on_confidential_issue) | ||||
|       end | ||||
| 
 | ||||
|  | @ -245,6 +253,7 @@ describe TodoService, services: true do | |||
|         service.new_merge_request(mr_assigned, author) | ||||
| 
 | ||||
|         should_create_todo(user: member, target: mr_assigned, action: Todo::MENTIONED) | ||||
|         should_create_todo(user: guest, target: mr_assigned, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: author, target: mr_assigned, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: john_doe, target: mr_assigned, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: non_member, target: mr_assigned, action: Todo::MENTIONED) | ||||
|  | @ -256,6 +265,7 @@ describe TodoService, services: true do | |||
|         service.update_merge_request(mr_assigned, author) | ||||
| 
 | ||||
|         should_create_todo(user: member, target: mr_assigned, action: Todo::MENTIONED) | ||||
|         should_create_todo(user: guest, target: mr_assigned, action: Todo::MENTIONED) | ||||
|         should_create_todo(user: john_doe, target: mr_assigned, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: author, target: mr_assigned, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: non_member, target: mr_assigned, action: Todo::MENTIONED) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue