diff --git a/app/finders/contributed_projects_finder.rb b/app/finders/contributed_projects_finder.rb index c1ef9dfefa7..f8c7f0c3167 100644 --- a/app/finders/contributed_projects_finder.rb +++ b/app/finders/contributed_projects_finder.rb @@ -14,6 +14,9 @@ class ContributedProjectsFinder < UnionFinder # Returns an ActiveRecord::Relation. # rubocop: disable CodeReuse/ActiveRecord def execute(current_user = nil) + # Do not show contributed projects if the user profile is private. + return Project.none unless can_read_profile?(current_user) + segments = all_projects(current_user) find_union(segments, Project).includes(:namespace).order_id_desc @@ -22,6 +25,10 @@ class ContributedProjectsFinder < UnionFinder private + def can_read_profile?(current_user) + Ability.allowed?(current_user, :read_user_profile, @user) + end + def all_projects(current_user) projects = [] diff --git a/changelogs/unreleased/security-contributed-projects.yml b/changelogs/unreleased/security-contributed-projects.yml new file mode 100644 index 00000000000..f745a2255ca --- /dev/null +++ b/changelogs/unreleased/security-contributed-projects.yml @@ -0,0 +1,5 @@ +--- +title: Fix contributed projects info still visible when user enable private profile +merge_request: +author: +type: security diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 27edf226ca3..af61026098b 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -206,6 +206,38 @@ describe UsersController do end end + describe 'GET #contributed' do + let(:project) { create(:project, :public) } + let(:current_user) { create(:user) } + + before do + sign_in(current_user) + + project.add_developer(public_user) + project.add_developer(private_user) + end + + context 'with public profile' do + it 'renders contributed projects' do + create(:push_event, project: project, author: public_user) + + get :contributed, params: { username: public_user.username } + + expect(assigns[:contributed_projects]).not_to be_empty + end + end + + context 'with private profile' do + it 'does not render contributed projects' do + create(:push_event, project: project, author: private_user) + + get :contributed, params: { username: private_user.username } + + expect(assigns[:contributed_projects]).to be_empty + end + end + end + describe 'GET #snippets' do before do sign_in(user) diff --git a/spec/finders/contributed_projects_finder_spec.rb b/spec/finders/contributed_projects_finder_spec.rb index 81fb4e3561c..ee84fd067d4 100644 --- a/spec/finders/contributed_projects_finder_spec.rb +++ b/spec/finders/contributed_projects_finder_spec.rb @@ -31,4 +31,16 @@ describe ContributedProjectsFinder do it { is_expected.to match_array([private_project, internal_project, public_project]) } end + + context 'user with private profile' do + it 'does not return contributed projects' do + private_user = create(:user, private_profile: true) + public_project.add_maintainer(private_user) + create(:push_event, project: public_project, author: private_user) + + projects = described_class.new(private_user).execute(current_user) + + expect(projects).to be_empty + end + end end