summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorFilipa Lacerda <filipa@gitlab.com>2018-05-17 15:40:39 +0100
committerFilipa Lacerda <filipa@gitlab.com>2018-05-17 15:40:39 +0100
commit49673de34f326a15d3358cb4ff22a73dfa5d4b20 (patch)
tree456d5744b1afb95ce12d7a2364f2dd7842b88a0d /lib
parent9e61d26c35acd6e60ac0fb0df711dbfdfda7c448 (diff)
parentd9b78477000dafc4f8b8fd7e795e97649b8c6718 (diff)
downloadgitlab-ce-46381-dropdown-mr-widget.tar.gz
Merge branch 'master' into 46381-dropdown-mr-widget46381-dropdown-mr-widget
* master: (40 commits) Add changelog Update quick_start_guide.md Resolve "Opening Project with invite but without accepting leads to 404 error page" Respect the inheritance chain between Ci::Build and CommitStatus Remove unneccessary imports fixed copy to cliboard button in embedded snippets Fix Error 500 viewing admin page due to statement timeouts Grant privileges after database is created Only setup db in the first checkout! Project Sidebar: Split CI/CD into CI/CD and Operations Fix GPM content types for Doorkeeper Workhorse to send raw diff and patch for commits Refactor out duplication in runner_policy.rb Remove unnecessary runner.is_shared? checks in api because they are handled by policy Allow admin to assign shared runner to project through API Change policy list_runner_jobs -> read_runner Rename User#ci_authorized_runners -> ci_owned_runners Improve efficiency of authorized_runner policy query Use can? policies for lib/api/runners.rb Allow group runners to be viewed/edited in API ...
Diffstat (limited to 'lib')
-rw-r--r--lib/api/groups.rb1
-rw-r--r--lib/api/runners.rb23
-rw-r--r--lib/api/v3/groups.rb1
-rw-r--r--lib/api/v3/runners.rb2
-rw-r--r--lib/gitlab/database/count.rb48
-rw-r--r--lib/gitlab/git/commit.rb25
-rw-r--r--lib/gitlab/git/repository.rb26
-rw-r--r--lib/gitlab/metrics/web_transaction.rb6
8 files changed, 68 insertions, 64 deletions
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 92e3d5cc10a..0d125cd7831 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -165,6 +165,7 @@ module API
group = find_group!(params[:id])
authorize! :admin_group, group
+ Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-ce/issues/46285')
destroy_conditionally!(group) do |group|
::Groups::DestroyService.new(group, current_user).execute
end
diff --git a/lib/api/runners.rb b/lib/api/runners.rb
index 5f2a9567605..5cb96d467c0 100644
--- a/lib/api/runners.rb
+++ b/lib/api/runners.rb
@@ -14,7 +14,7 @@ module API
use :pagination
end
get do
- runners = filter_runners(current_user.ci_authorized_runners, params[:scope], without: %w(specific shared))
+ runners = filter_runners(current_user.ci_owned_runners, params[:scope], without: %w(specific shared))
present paginate(runners), with: Entities::Runner
end
@@ -184,40 +184,35 @@ module API
def authenticate_show_runner!(runner)
return if runner.is_shared || current_user.admin?
- forbidden!("No access granted") unless user_can_access_runner?(runner)
+ forbidden!("No access granted") unless can?(current_user, :read_runner, runner)
end
def authenticate_update_runner!(runner)
return if current_user.admin?
- forbidden!("Runner is shared") if runner.is_shared?
- forbidden!("No access granted") unless user_can_access_runner?(runner)
+ forbidden!("No access granted") unless can?(current_user, :update_runner, runner)
end
def authenticate_delete_runner!(runner)
return if current_user.admin?
- forbidden!("Runner is shared") if runner.is_shared?
forbidden!("Runner associated with more than one project") if runner.projects.count > 1
- forbidden!("No access granted") unless user_can_access_runner?(runner)
+ forbidden!("No access granted") unless can?(current_user, :delete_runner, runner)
end
def authenticate_enable_runner!(runner)
- forbidden!("Runner is shared") if runner.is_shared?
- forbidden!("Runner is locked") if runner.locked?
+ forbidden!("Runner is a group runner") if runner.group_type?
+
return if current_user.admin?
- forbidden!("No access granted") unless user_can_access_runner?(runner)
+ forbidden!("Runner is locked") if runner.locked?
+ forbidden!("No access granted") unless can?(current_user, :assign_runner, runner)
end
def authenticate_list_runners_jobs!(runner)
return if current_user.admin?
- forbidden!("No access granted") unless user_can_access_runner?(runner)
- end
-
- def user_can_access_runner?(runner)
- current_user.ci_authorized_runners.exists?(runner.id)
+ forbidden!("No access granted") unless can?(current_user, :read_runner, runner)
end
end
end
diff --git a/lib/api/v3/groups.rb b/lib/api/v3/groups.rb
index 2c52d21fa1c..3844fd4810d 100644
--- a/lib/api/v3/groups.rb
+++ b/lib/api/v3/groups.rb
@@ -131,6 +131,7 @@ module API
delete ":id" do
group = find_group!(params[:id])
authorize! :admin_group, group
+ Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-ce/issues/46285')
present ::Groups::DestroyService.new(group, current_user).execute, with: Entities::GroupDetail, current_user: current_user
end
diff --git a/lib/api/v3/runners.rb b/lib/api/v3/runners.rb
index c6d9957d452..8a5c46805bd 100644
--- a/lib/api/v3/runners.rb
+++ b/lib/api/v3/runners.rb
@@ -58,7 +58,7 @@ module API
end
def user_can_access_runner?(runner)
- current_user.ci_authorized_runners.exists?(runner.id)
+ current_user.ci_owned_runners.exists?(runner.id)
end
end
end
diff --git a/lib/gitlab/database/count.rb b/lib/gitlab/database/count.rb
new file mode 100644
index 00000000000..3374203960e
--- /dev/null
+++ b/lib/gitlab/database/count.rb
@@ -0,0 +1,48 @@
+# For large tables, PostgreSQL can take a long time to count rows due to MVCC.
+# We can optimize this by using the reltuples count as described in https://wiki.postgresql.org/wiki/Slow_Counting.
+module Gitlab
+ module Database
+ module Count
+ CONNECTION_ERRORS =
+ if defined?(PG)
+ [
+ ActionView::Template::Error,
+ ActiveRecord::StatementInvalid,
+ PG::Error
+ ].freeze
+ else
+ [
+ ActionView::Template::Error,
+ ActiveRecord::StatementInvalid
+ ].freeze
+ end
+
+ def self.approximate_count(model)
+ return model.count unless Gitlab::Database.postgresql?
+
+ execute_estimate_if_updated_recently(model) || model.count
+ end
+
+ def self.execute_estimate_if_updated_recently(model)
+ ActiveRecord::Base.connection.select_value(postgresql_estimate_query(model)).to_i if reltuples_updated_recently?(model)
+ rescue *CONNECTION_ERRORS
+ end
+
+ def self.reltuples_updated_recently?(model)
+ time = "to_timestamp(#{1.hour.ago.to_i})"
+ query = <<~SQL
+ SELECT 1 FROM pg_stat_user_tables WHERE relname = '#{model.table_name}' AND
+ (last_vacuum > #{time} OR last_autovacuum > #{time} OR last_analyze > #{time} OR last_autoanalyze > #{time})
+ SQL
+
+ ActiveRecord::Base.connection.select_all(query).count > 0
+ rescue *CONNECTION_ERRORS
+ false
+ end
+
+ def self.postgresql_estimate_query(model)
+ "SELECT reltuples::bigint AS estimate FROM pg_class where relname = '#{model.table_name}'"
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb
index fabcd46c8e9..d79a4dbeee4 100644
--- a/lib/gitlab/git/commit.rb
+++ b/lib/gitlab/git/commit.rb
@@ -342,21 +342,6 @@ module Gitlab
parent_ids.first
end
- # Shows the diff between the commit's parent and the commit.
- #
- # Cuts out the header and stats from #to_patch and returns only the diff.
- #
- # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/324
- def to_diff
- Gitlab::GitalyClient.migrate(:commit_patch, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled|
- if is_enabled
- @repository.gitaly_commit_client.patch(id)
- else
- rugged_diff_from_parent.patch
- end
- end
- end
-
# Returns a diff object for the changes from this commit's first parent.
# If there is no parent, then the diff is between this commit and an
# empty repo. See Repository#diff for keys allowed in the +options+
@@ -432,16 +417,6 @@ module Gitlab
Gitlab::Git::CommitStats.new(@repository, self)
end
- def to_patch(options = {})
- begin
- rugged_commit.to_mbox(options)
- rescue Rugged::InvalidError => ex
- if ex.message =~ /commit \w+ is a merge commit/i
- 'Patch format is not currently supported for merge commits.'
- end
- end
- end
-
# Get ref names collection
#
# Ex.
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 25487f53999..061865a7acf 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -776,13 +776,9 @@ module Gitlab
end
def add_branch(branch_name, user:, target:)
- gitaly_migrate(:operation_user_create_branch, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled|
- if is_enabled
- gitaly_add_branch(branch_name, user, target)
- else
- rugged_add_branch(branch_name, user, target)
- end
- end
+ gitaly_operation_client.user_create_branch(branch_name, user, target)
+ rescue GRPC::FailedPrecondition => ex
+ raise InvalidRef, ex
end
def add_tag(tag_name, user:, target:, message: nil)
@@ -2197,22 +2193,6 @@ module Gitlab
end
end
- def gitaly_add_branch(branch_name, user, target)
- gitaly_operation_client.user_create_branch(branch_name, user, target)
- rescue GRPC::FailedPrecondition => ex
- raise InvalidRef, ex
- end
-
- def rugged_add_branch(branch_name, user, target)
- target_object = Ref.dereference_object(lookup(target))
- raise InvalidRef.new("target not found: #{target}") unless target_object
-
- OperationService.new(user, self).add_branch(branch_name, target_object.oid)
- find_branch(branch_name)
- rescue Rugged::ReferenceError => ex
- raise InvalidRef, ex
- end
-
def rugged_cherry_pick(user:, commit:, branch_name:, message:, start_branch_name:, start_repository:)
OperationService.new(user, self).with_branch(
branch_name,
diff --git a/lib/gitlab/metrics/web_transaction.rb b/lib/gitlab/metrics/web_transaction.rb
index 7cf33ca9e8a..3799aaebf1c 100644
--- a/lib/gitlab/metrics/web_transaction.rb
+++ b/lib/gitlab/metrics/web_transaction.rb
@@ -28,7 +28,11 @@ module Gitlab
controller = @env[CONTROLLER_KEY]
action = "#{controller.action_name}"
- suffix = controller.request_format
+
+ # Devise exposes a method called "request_format" that does the below.
+ # However, this method is not available to all controllers (e.g. certain
+ # Doorkeeper controllers). As such we use the underlying code directly.
+ suffix = controller.request.format.try(:ref)
if suffix && suffix != :html
action += ".#{suffix}"