summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAngelo Lakra <alakra@comverge.com>2013-10-07 20:10:08 -0600
committerAngelo Lakra <angelo.lakra@gmail.com>2013-10-08 00:43:14 -0600
commit8cc0ad78ffbc11455c9e876bf08683ce836165ef (patch)
treec5e4796956a67b489a105ce475724fdcda5db677
parent519cce2c5149c21cf571ef73c974bffbef1a6398 (diff)
downloadgitlab-ci-8cc0ad78ffbc11455c9e876bf08683ce836165ef.tar.gz
Adding user access checking per project
* Made :per_page and :page on Project.from_gitlab optional for API calls * Added call to retrieve Gitlab CI projects that are not only authorized, but "owned"
-rw-r--r--app/models/project.rb9
-rw-r--r--app/models/user_session.rb7
-rw-r--r--lib/api/projects.rb38
-rw-r--r--spec/requests/projects_spec.rb59
4 files changed, 90 insertions, 23 deletions
diff --git a/app/models/project.rb b/app/models/project.rb
index b9de85c..e324dc5 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -27,7 +27,6 @@ class Project < ActiveRecord::Base
has_many :runner_projects, dependent: :destroy
has_many :runners, through: :runner_projects
-
#
# Validations
#
@@ -45,11 +44,9 @@ class Project < ActiveRecord::Base
before_validation :set_default_values
def self.from_gitlab(user, page, per_page, scope = :owned)
- opts = {
- private_token: user.private_token,
- per_page: per_page,
- page: page,
- }
+ opts = { private_token: user.private_token }
+ opts[:per_page] = per_page if per_page.present?
+ opts[:page] = page if page.present?
projects = Network.new.projects(user.url, opts, scope)
diff --git a/app/models/user_session.rb b/app/models/user_session.rb
index d964cf3..a29c705 100644
--- a/app/models/user_session.rb
+++ b/app/models/user_session.rb
@@ -29,7 +29,12 @@ class UserSession
user = block.call(url, Network.new, options)
if user
- return User.new(user.merge("url" => url))
+ verified_options = user.merge({
+ "url" => url,
+ "private_token" => options[:private_token]
+ })
+
+ return User.new(verified_options)
else
nil
end
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 7bd497d..c482f4a 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -12,15 +12,36 @@ module API
# GET /projects/:id
get ":id" do
project = Project.find(params[:id])
- present project, with: Entities::Project
+
+ if current_user.can_access_project?(project.gitlab_id)
+ present project, with: Entities::Project
+ else
+ unauthorized!
+ end
end
- # Retrieve info for aall Gitlab CI projects
+ # Retrieve all Gitlab CI projects that the user has access to
#
# Example Request:
# GET /projects
get do
- projects = Project.all
+ gitlab_projects = Project.from_gitlab(current_user, nil, nil, :authorized)
+ ids = gitlab_projects.map { |project| project.id }
+
+ projects = Project.where("gitlab_id IN (?)", ids).all
+ present projects, with: Entities::Project
+ end
+
+ # Retrieve all Gitlab CI projects that the user owns
+ #
+ # Example Request:
+ # GET /projects/owned
+ get "owned" do
+ byebug
+ gitlab_projects = Project.from_gitlab(current_user, nil, nil, :owned)
+ ids = gitlab_projects.map { |project| project.id }
+
+ projects = Project.where("gitlab_id IN (?)", ids).all
present projects, with: Entities::Project
end
@@ -38,9 +59,6 @@ module API
post do
required_attributes! [:name, :gitlab_id, :gitlab_url, :ssh_url_to_repo]
- # TODO: Check if this has automatic filtering of attributes
- # via the Grape API
-
filtered_params = {
:name => params[:name],
:gitlab_id => params[:gitlab_id],
@@ -75,7 +93,7 @@ module API
put ":id" do
project = Project.find(params[:id])
- if project.present?
+ if project.present? && current_user.can_access_project?(project.gitlab_id)
attrs = attributes_for_keys [:name, :gitlab_id, :gitlab_url, :scripts, :default_ref, :ssh_url_to_repo]
if project.update_attributes(attrs)
@@ -98,7 +116,7 @@ module API
delete ":id" do
project = Project.find(params[:id])
- if project.present?
+ if project.present? && current_user.can_access_project?(project.gitlab_id)
project.destroy
else
not_found!
@@ -113,6 +131,8 @@ module API
# Example Request:
# POST /projects/:id/runners/:runner_id
post ":id/runners/:runner_id" do
+ unauthorized! unless current_user.can_access_project?(params[:id])
+
project_exists = Project.exists?(params[:id])
runner_exists = Runner.exists?(params[:runner_id])
@@ -141,6 +161,8 @@ module API
# Example Request:
# DELETE /projects/:id/runners/:runner_id
delete ":id/runners/:runner_id" do
+ unauthorized! unless current_user.can_access_project?(params[:id])
+
project_exists = Project.exists?(params[:id])
runner_exists = Runner.exists?(params[:runner_id])
diff --git a/spec/requests/projects_spec.rb b/spec/requests/projects_spec.rb
index 851b42d..dd55938 100644
--- a/spec/requests/projects_spec.rb
+++ b/spec/requests/projects_spec.rb
@@ -6,6 +6,8 @@ describe API::API do
let(:private_token) { "A" }
let(:gitlab_url) { GitlabCi.config.allowed_gitlab_urls.first }
let(:auth_url) { File.join(gitlab_url, Network::API_PREFIX, "user.json") }
+ let(:projects_authorized_url) { File.join(gitlab_url, Network::API_PREFIX, "projects.json") }
+ let(:projects_owned_url) { File.join(gitlab_url, Network::API_PREFIX, "projects/owned.json") }
let(:options) {
{
:private_token => private_token,
@@ -23,16 +25,57 @@ describe API::API do
:body => { :url => "http://myurl" }.to_json)
end
- describe "GET /projects" do
- let(:project) { FactoryGirl.create(:project) }
+ context "requests for scoped projects" do
+ let(:project1) { FactoryGirl.create(:project, :name => "Project 1") }
+ let(:project2) { FactoryGirl.create(:project, :name => "Project 2") }
- before { project }
+ before do
+ # NOTE: Making project ids the same as the gitlab id for ease of matching
+ projects.map { |project| project.update_attribute(:gitlab_id, project.id) }
+ end
- it "should return all projects on the CI instance" do
- get api("/projects"), options
- response.status.should == 200
- json_response.count.should == 1
- json_response.first["id"].should == project.id
+ describe "GET /projects" do
+ let(:projects) { [project1, project2] }
+
+ before do
+ # stub authentication endpoint for authorized projects
+ stub_request(:get, projects_authorized_url).
+ with(:query => { :private_token => private_token }).
+ to_return(
+ :status => 200,
+ :headers => {"Content-Type" => "application/json"},
+ :body => projects.to_json)
+ end
+
+ it "should return all projects on the CI instance" do
+ byebug
+ get api("/projects"), options
+ response.status.should == 200
+ json_response.count.should == 2
+ json_response.first["id"].should == project1.id
+ json_response.last["id"].should == project2.id
+ end
+ end
+
+ describe "GET /projects/owned" do
+ let(:projects) { [project2] }
+
+ before do
+ # stub authentication endpoint for owned projects
+ stub_request(:get, projects_owned_url).
+ with(:query => { :private_token => private_token }).
+ to_return(
+ :status => 200,
+ :headers => {"Content-Type" => "application/json"},
+ :body => projects.to_json)
+ end
+
+ it "should return all projects on the CI instance" do
+ get api("/projects/owned"), options
+ response.status.should == 200
+ json_response.count.should == 1
+ json_response.first["id"].should == project2.id
+ end
end
end