diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb index 71acc244a9170b488423318b2dd091c4cce98295..c08eb8115322e8be3b987ba7325a0beac3b71f33 100644 --- a/app/controllers/dashboard/projects_controller.rb +++ b/app/controllers/dashboard/projects_controller.rb @@ -28,7 +28,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController end def starred - @projects = current_user.starred_projects.sorted_by_activity + @projects = current_user.viewable_starred_projects.sorted_by_activity @projects = filter_projects(@projects) @projects = @projects.includes(:namespace, :forked_from_project, :tags) @projects = @projects.sort(@sort = params[:sort]) diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 1dce4a21729f88fea4b5d2cee06c933c63fc5e8a..4dda4e51f6a5a2440e48a6e779d50e9817906cd3 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -25,7 +25,7 @@ class DashboardController < Dashboard::ApplicationController def load_events projects = if params[:filter] == "starred" - current_user.starred_projects + current_user.viewable_starred_projects else current_user.authorized_projects end diff --git a/app/models/user.rb b/app/models/user.rb index 1e4814641d1b02e4e02ac5a96902a3f76e8896f1..a0115957f00ac485dab7e546a6d45254ea9cf62b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -381,6 +381,11 @@ class User < ActiveRecord::Base Project.where("projects.id IN (#{projects_union.to_sql})") end + def viewable_starred_projects + starred_projects.where("projects.visibility_level IN (?) OR projects.id IN (#{projects_union.to_sql})", + [Gitlab::VisibilityLevel::PUBLIC, Gitlab::VisibilityLevel::INTERNAL]) + end + def owned_projects @owned_projects ||= Project.where('namespace_id IN (?) OR namespace_id = ?', diff --git a/lib/api/projects.rb b/lib/api/projects.rb index cc2c7a0c5032ece375a194ff363b73e8438bc6ef..9b59577267575b564277300cd64208f7690ef2af 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -44,7 +44,7 @@ module API # Example Request: # GET /projects/starred get '/starred' do - @projects = current_user.starred_projects + @projects = current_user.viewable_starred_projects @projects = filter_projects(@projects) @projects = paginate @projects present @projects, with: Entities::Project diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 26d4e139396b177d9892b19cc356a3d8af565b87..06d1ca3b7dadafac6420c32cda5d081c44a490cb 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -233,6 +233,8 @@ describe User, models: true do @project = create :project, namespace: @user.namespace @project_2 = create :project, group: create(:group) # Grant MASTER access to the user @project_3 = create :project, group: create(:group) # Grant DEVELOPER access to the user + @project_4 = create :project, group: create(:group) + @project_5 = create :project, group: create(:group) @project_2.team << [@user, :master] @project_3.team << [@user, :developer] @@ -782,4 +784,26 @@ describe User, models: true do it { is_expected.to eq([private_project]) } end + + describe '#viewable_starred_projects' do + let(:user) { create(:user) } + let(:public_project) { create(:project, :public) } + let(:private_project) { create(:project, :private) } + let(:private_viewable_project) { create(:project, :private) } + let(:viewable?) { -> (project) { user.can?(:read_project, project) } } + let(:projects) { [public_project, private_project, private_viewable_project] } + + before do + private_viewable_project.team << [user, Gitlab::Access::MASTER] + projects.each { |project| user.toggle_star(project) } + end + + it 'returns only starred projects the user can view' do + expect(user.viewable_starred_projects).to all(satisfy(&viewable?)) + end + + it 'rejects only starred projects the user can not view' do + expect(projects - user.viewable_starred_projects).not_to include(satisfy(&viewable?)) + end + end end diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 66193eac051e1592ec0e00d689688cecccbbbdfb..f167813e07dcfae10063fa51d8cfeba8945c3866 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -10,20 +10,20 @@ describe API::API, api: true do let(:admin) { create(:admin) } let(:project) { create(:project, creator_id: user.id, namespace: user.namespace) } let(:project2) { create(:project, path: 'project2', creator_id: user.id, namespace: user.namespace) } - let(:project3) { create(:project, path: 'project3', creator_id: user.id, namespace: user.namespace) } let(:snippet) { create(:project_snippet, :public, author: user, project: project, title: 'example') } let(:project_member) { create(:project_member, :master, user: user, project: project) } let(:project_member2) { create(:project_member, :developer, user: user3, project: project) } let(:user4) { create(:user) } let(:project3) do create(:project, + :private, name: 'second_project', path: 'second_project', creator_id: user.id, namespace: user.namespace, merge_requests_enabled: false, issues_enabled: false, wiki_enabled: false, - snippets_enabled: false, visibility_level: 0) + snippets_enabled: false) end let(:project_member3) do create(:project_member, @@ -164,21 +164,18 @@ describe API::API, api: true do end describe 'GET /projects/starred' do + let(:public_project) { create(:project, :public) } + before do - admin.starred_projects << project - admin.save! + project_member2 + user3.update_attributes(starred_projects: [project, project2, project3, public_project]) end - it 'should return the starred projects' do - get api('/projects/all', admin) + it 'should return the starred projects viewable by the user' do + get api('/projects/starred', user3) expect(response.status).to eq(200) expect(json_response).to be_an Array - - expect(json_response).to satisfy do |response| - response.one? do |entry| - entry['name'] == project.name - end - end + expect(json_response.map { |project| project['id'] }).to contain_exactly(project.id, public_project.id) end end