summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Speicher <robert@gitlab.com>2016-05-11 12:49:29 +0000
committerRobert Speicher <robert@gitlab.com>2016-05-11 12:49:29 +0000
commit24f353edc4e90a7846bb6706f6b89e1bb6db7469 (patch)
tree7dee14d6f545f26de63e740d5194cba1f3249746
parentd526cda5028c9b55241a6996f32cc6a967e8fcba (diff)
parentacd8930c46c06312f87c5ea0bb549b5435feece8 (diff)
downloadgitlab-ce-24f353edc4e90a7846bb6706f6b89e1bb6db7469.tar.gz
Merge branch '17249-starred' into 'master'
Restrict starred projects to viewable ones `User#starred_projects` doesn't perform any visibility checks. This has a couple of problems: 1. It assumes a user can always view all of their starred projects in perpetuity (project not changed to private, access revoked, etc.). 2. It assumes that we'll only ever allow a user to star a project they can view. This is currently the case, but bugs happen. Add `User#viewable_starred_projects` to filter the starred projects by those the user either has explicit access to, or are public or internal. Then use that in all places where we list the user's starred projects. Closes #17249. See merge request !4108
-rw-r--r--app/controllers/dashboard/projects_controller.rb2
-rw-r--r--app/controllers/dashboard_controller.rb2
-rw-r--r--app/models/user.rb5
-rw-r--r--lib/api/projects.rb2
-rw-r--r--spec/models/user_spec.rb19
-rw-r--r--spec/requests/api/projects_spec.rb21
6 files changed, 36 insertions, 15 deletions
diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb
index 71acc244a91..c08eb811532 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 1dce4a21729..4dda4e51f6a 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 1e4814641d1..489bff3fa4a 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})",
+ [Project::PUBLIC, Project::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 cc2c7a0c503..9b595772675 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 26d4e139396..10e7e693571 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -782,4 +782,23 @@ 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(:empty_project, :public) }
+ let(:private_project) { create(:empty_project, :private) }
+ let(:private_viewable_project) { create(:empty_project, :private) }
+
+ before do
+ private_viewable_project.team << [user, Gitlab::Access::MASTER]
+
+ [public_project, private_project, private_viewable_project].each do |project|
+ user.toggle_star(project)
+ end
+ end
+
+ it 'returns only starred projects the user can view' do
+ expect(user.viewable_starred_projects).not_to include(private_project)
+ end
+ end
end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 66193eac051..f167813e07d 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