Commit 76704c79 authored by Phil Hughes's avatar Phil Hughes

Merge branch 'master' into ph-inline-js

parents 425dbdd2 842bcfa7
7.5
\ No newline at end of file
......@@ -2,6 +2,18 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 9.4.1 (2017-07-25)
- Fix pipeline_schedules pages throwing error 500 (when ref is empty). !12983
- Fix editing project with container images present. !13028
- Fix some invalid entries in PO files. !13032
- Fix cross site request protection when logging in as a regular user when LDAP is enabled. !13049
- Fix bug causing metrics files to be truncated. !35420
- Fix anonymous access to public projects in groups with pending invites.
- Fixed issue boards sidebar close icon size.
- Fixed duplicate new milestone buttons when new navigation is turned on.
- Fix margins in the mini graph for pipeline in commits box.
## 9.4.0 (2017-07-22)
- Add blame view age mapping. !7198 (Jeff Stubler)
......
......@@ -114,8 +114,8 @@ scheduling into milestones. Labelling is a task for everyone.
Most issues will have labels for at least one of the following:
- Type: ~"feature proposal", ~bug, ~customer, etc.
- Subject: ~wiki, ~"container registry", ~ldap, ~api, etc.
- Team: ~CI, ~Discussion, ~Edge, ~Frontend, ~Platform, etc.
- Subject: ~wiki, ~"container registry", ~ldap, ~api, ~frontend, etc.
- Team: ~CI, ~Discussion, ~Edge, ~Platform, etc.
- Priority: ~Deliverable, ~Stretch
All labels, their meaning and priority are defined on the
......@@ -278,7 +278,7 @@ For feature proposals for EE, open an issue on the
In order to help track the feature proposals, we have created a
[`feature proposal`][fpl] label. For the time being, users that are not members
of the project cannot add labels. You can instead ask one of the [core team]
members to add the label `feature proposal` to the issue or add the following
members to add the label ~"feature proposal" to the issue or add the following
code snippet right after your description in a new line: `~"feature proposal"`.
Please keep feature proposals as small and simple as possible, complex ones
......
......@@ -16,6 +16,7 @@ gem 'mysql2', '~> 0.4.5', group: :mysql
gem 'pg', '~> 0.18.2', group: :postgres
gem 'rugged', '~> 0.25.1.1'
gem 'grape-route-helpers', '~> 2.0.0'
gem 'faraday', '~> 0.12'
......@@ -60,7 +61,8 @@ gem 'browser', '~> 2.2'
# LDAP Auth
# GitLab fork with several improvements to original library. For full list of changes
# see https://github.com/intridea/omniauth-ldap/compare/master...gitlabhq:master
gem 'gitlab_omniauth-ldap', '~> 1.2.1', require: 'omniauth-ldap'
gem 'gitlab_omniauth-ldap', '~> 2.0.3', require: 'omniauth-ldap'
gem 'net-ldap'
# Git Wiki
# Required manually in config/initializers/gollum.rb to control load order
......@@ -164,7 +166,7 @@ gem 'rainbow', '~> 2.2'
gem 'settingslogic', '~> 2.0.9'
# Linear-time regex library for untrusted regular expressions
gem 're2', '~> 1.1.0'
gem 're2', '~> 1.1.1'
# Misc
......
......@@ -288,11 +288,11 @@ GEM
mime-types (>= 1.16, < 3)
posix-spawn (~> 0.3)
gitlab-markup (1.5.1)
gitlab_omniauth-ldap (1.2.1)
net-ldap (~> 0.9)
omniauth (~> 1.0)
pyu-ruby-sasl (~> 0.0.3.1)
rubyntlm (~> 0.3)
gitlab_omniauth-ldap (2.0.3)
net-ldap (~> 0.16)
omniauth (~> 1.3)
pyu-ruby-sasl (>= 0.0.3.3, < 0.1)
rubyntlm (~> 0.5)
globalid (0.3.7)
activesupport (>= 4.1.0)
gollum-grit_adapter (1.0.1)
......@@ -345,6 +345,10 @@ GEM
grape-entity (0.6.0)
activesupport
multi_json (>= 1.3.2)
grape-route-helpers (2.0.0)
activesupport
grape (~> 0.16, >= 0.16.0)
rake
grpc (1.4.0)
google-protobuf (~> 3.1)
googleauth (~> 0.5.1)
......@@ -467,7 +471,7 @@ GEM
mustermann-grape (1.0.0)
mustermann (~> 1.0.0)
mysql2 (0.4.5)
net-ldap (0.12.1)
net-ldap (0.16.0)
netrc (0.11.0)
nokogiri (1.6.8.1)
mini_portile2 (~> 2.1.0)
......@@ -656,7 +660,7 @@ GEM
debugger-ruby_core_source (~> 1.3)
rdoc (4.2.2)
json (~> 1.4)
re2 (1.1.0)
re2 (1.1.1)
recaptcha (3.0.0)
json
recursive-open-struct (1.0.0)
......@@ -740,7 +744,7 @@ GEM
nokogiri (>= 1.5.10)
ruby_parser (3.9.0)
sexp_processor (~> 4.1)
rubyntlm (0.5.2)
rubyntlm (0.6.2)
rubypants (0.2.0)
rubyzip (1.2.1)
rufus-scheduler (3.4.0)
......@@ -974,13 +978,14 @@ DEPENDENCIES
github-linguist (~> 4.7.0)
gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-markup (~> 1.5.1)
gitlab_omniauth-ldap (~> 1.2.1)
gitlab_omniauth-ldap (~> 2.0.3)
gollum-lib (~> 4.2)
gollum-rugged_adapter (~> 0.4.4)
gon (~> 6.1.0)
google-api-client (~> 0.8.6)
grape (~> 0.19.2)
grape-entity (~> 0.6.0)
grape-route-helpers (~> 2.0.0)
haml_lint (~> 0.21.0)
hamlit (~> 2.6.1)
hashie-forbidden_attributes
......@@ -1008,6 +1013,7 @@ DEPENDENCIES
minitest (~> 5.7.0)
mousetrap-rails (~> 1.4.6)
mysql2 (~> 0.4.5)
net-ldap
nokogiri (~> 1.6.7, >= 1.6.7.2)
oauth2 (~> 1.4)
octokit (~> 4.6.2)
......@@ -1055,7 +1061,7 @@ DEPENDENCIES
raindrops (~> 0.18)
rblineprof (~> 0.3.6)
rdoc (~> 4.2)
re2 (~> 1.1.0)
re2 (~> 1.1.1)
recaptcha (~> 3.0)
redcarpet (~> 3.4)
redis (~> 3.2)
......
......@@ -20,6 +20,8 @@
/* global NamespaceSelects */
/* global Project */
/* global ProjectAvatar */
/* global MergeRequest */
/* global Compare */
/* global CompareAutocomplete */
/* global ProjectNew */
/* global ProjectShow */
......@@ -228,6 +230,19 @@ import initIssuableSidebar from './init_issuable_sidebar';
new gl.IssuableTemplateSelectors();
break;
case 'projects:merge_requests:creations:new':
const mrNewCompareNode = document.querySelector('.js-merge-request-new-compare');
if (mrNewCompareNode) {
new Compare({
targetProjectUrl: mrNewCompareNode.dataset.targetProjectUrl,
sourceBranchUrl: mrNewCompareNode.dataset.sourceBranchUrl,
targetBranchUrl: mrNewCompareNode.dataset.targetBranchUrl,
});
} else {
const mrNewSubmitNode = document.querySelector('.js-merge-request-new-submit');
new MergeRequest({
action: mrNewSubmitNode.dataset.mrSubmitAction,
});
}
case 'projects:merge_requests:creations:diffs':
case 'projects:merge_requests:edit':
new gl.Diff();
......@@ -267,8 +282,14 @@ import initIssuableSidebar from './init_issuable_sidebar';
new gl.Diff();
shortcut_handler = new ShortcutsIssuable(true);
new ZenMode();
initIssuableSidebar();
initNotes();
const mrShowNode = document.querySelector('.merge-request');
window.mergeRequest = new MergeRequest({
action: mrShowNode.dataset.mrAction,
});
break;
case 'dashboard:activity':
new gl.Activities();
......
......@@ -3,10 +3,10 @@ document.addEventListener('DOMContentLoaded', () => {
modal: true,
show: false,
});
$('.how_to_merge_link').bind('click', () => {
$('.how_to_merge_link').on('click', () => {
modal.show();
});
$('.modal-header .close').bind('click', () => {
$('.modal-header .close').on('click', () => {
modal.hide();
});
});
......@@ -175,7 +175,7 @@ import Cookies from 'js-cookie';
getConflictsCountText() {
const count = this.getConflictsCount();
const text = count ? 'conflicts' : 'conflict';
const text = count > 1 ? 'conflicts' : 'conflict';
return `${count} ${text}`;
},
......
......@@ -108,7 +108,8 @@ export default {
</div>
<mr-widget-memory-usage
v-if="deployment.metrics_url"
:metricsUrl="deployment.metrics_url"
:metrics-url="deployment.metrics_url"
:metrics-monitoring-url="deployment.metrics_monitoring_url"
/>
</div>
</div>
......
......@@ -7,7 +7,14 @@ import MRWidgetService from '../services/mr_widget_service';
export default {
name: 'MemoryUsage',
props: {
metricsUrl: { type: String, required: true },
metricsUrl: {
type: String,
required: true,
},
metricsMonitoringUrl: {
type: String,
required: true,
},
},
data() {
return {
......@@ -124,7 +131,7 @@ export default {
<p
v-if="shouldShowMemoryGraph"
class="usage-info js-usage-info">
Memory usage <b>{{memoryChangeType}}</b> from {{memoryFrom}}MB to {{memoryTo}}MB
<a :href="metricsMonitoringUrl">Memory</a> usage <b>{{memoryChangeType}}</b> from {{memoryFrom}}MB to {{memoryTo}}MB
</p>
<p
v-if="shouldShowLoadFailure"
......
......@@ -21,6 +21,11 @@ header.navbar-gitlab-new {
padding-right: 0;
color: currentColor;
img {
height: 28px;
margin-right: 10px;
}
> a {
display: flex;
align-items: center;
......
......@@ -211,6 +211,10 @@
-webkit-overflow-scrolling: touch;
}
&.affix-top .issuable-sidebar {
height: 100%;
}
&.right-sidebar-expanded {
width: $gutter_width;
......
......@@ -597,7 +597,7 @@
}
// Dropdown button in mini pipeline graph
.mini-pipeline-graph-dropdown-toggle {
button.mini-pipeline-graph-dropdown-toggle {
border-radius: 100px;
background-color: $white-light;
border-width: 1px;
......@@ -608,6 +608,7 @@
padding: 0;
transition: all 0.2s linear;
position: relative;
vertical-align: middle;
> .fa.fa-caret-down {
position: absolute;
......
......@@ -76,11 +76,11 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
params.delete(:domain_blacklist_raw) if params[:domain_blacklist_file]
params.require(:application_setting).permit(
application_setting_params_ce
application_setting_params_attributes
)
end
def application_setting_params_ce
def application_setting_params_attributes
[
:admin_notification_email,
:after_sign_out_path,
......
class Admin::DashboardController < Admin::ApplicationController
def index
@projects = Project.with_route.limit(10)
@projects = Project.without_deleted.with_route.limit(10)
@users = User.limit(10)
@groups = Group.with_route.limit(10)
end
......
......@@ -22,6 +22,7 @@ class Projects::ApplicationController < ApplicationController
def project
return @project if @project
return nil unless params[:project_id] || params[:id]
path = File.join(params[:namespace_id], params[:project_id] || params[:id])
auth_proc = ->(project) { !project.pending_delete? }
......
......@@ -223,12 +223,18 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
if can?(current_user, :read_environment, environment) && environment.has_metrics?
metrics_project_environment_deployment_path(environment.project, environment, deployment)
end
metrics_monitoring_url =
if can?(current_user, :read_environment, environment)
environment_metrics_path(environment)
end
{
id: environment.id,
name: environment.name,
url: project_environment_path(project, environment),
metrics_url: metrics_url,
metrics_monitoring_url: metrics_monitoring_url,
stop_url: stop_url,
external_url: environment.external_url,
external_url_formatted: environment.formatted_external_url,
......
......@@ -296,10 +296,10 @@ class ProjectsController < Projects::ApplicationController
def project_params
params.require(:project)
.permit(project_params_ce)
.permit(project_params_attributes)
end
def project_params_ce
def project_params_attributes
[
:avatar,
:build_allow_git_fetch,
......
......@@ -11,6 +11,7 @@
# group_id: integer
# project_id: integer
# milestone_title: string
# author_id: integer
# assignee_id: integer
# search: string
# label_name: string
......
......@@ -18,7 +18,8 @@ module SystemNoteHelper
'milestone' => 'icon_clock_o',
'discussion' => 'icon_comment_o',
'moved' => 'icon_arrow_circle_o_right',
'outdated' => 'icon_edit'
'outdated' => 'icon_edit',
'duplicate' => 'icon_clone'
}.freeze
def icon_for_system_note(note)
......
......@@ -21,7 +21,7 @@ module Ci
has_many :merge_requests, foreign_key: "head_pipeline_id"
has_many :pending_builds, -> { pending }, foreign_key: :commit_id, class_name: 'Ci::Build'
has_many :retryable_builds, -> { latest.failed_or_canceled }, foreign_key: :commit_id, class_name: 'Ci::Build'
has_many :retryable_builds, -> { latest.failed_or_canceled.includes(:project) }, foreign_key: :commit_id, class_name: 'Ci::Build'
has_many :cancelable_statuses, -> { cancelable }, foreign_key: :commit_id, class_name: 'CommitStatus'
has_many :manual_actions, -> { latest.manual_actions.includes(:project) }, foreign_key: :commit_id, class_name: 'Ci::Build'
has_many :artifacts, -> { latest.with_artifacts_not_expired.includes(:project) }, foreign_key: :commit_id, class_name: 'Ci::Build'
......
......@@ -40,10 +40,6 @@ module Ci
update_attribute(:active, false)
end
def runnable_by_owner?
Ability.allowed?(owner, :create_pipeline, project)
end
def set_next_run_at
self.next_run_at = Gitlab::Ci::CronParser.new(cron, cron_timezone).next_time_from(Time.now)
end
......
......@@ -17,7 +17,13 @@ module ProtectedRef
class_methods do
def protected_ref_access_levels(*types)
types.each do |type|
has_many :"#{type}_access_levels", dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
# We need to set `inverse_of` to make sure the `belongs_to`-object is set
# when creating children using `accepts_nested_attributes_for`.
#
# If we don't `protected_branch` or `protected_tag` would be empty and
# `project` cannot be delegated to it, which in turn would cause validations
# to fail.
has_many :"#{type}_access_levels", dependent: :destroy, inverse_of: self.model_name.singular # rubocop:disable Cop/ActiveRecordDependent
validates :"#{type}_access_levels", length: { is: 1, message: "are restricted to a single instance per #{self.model_name.human}." }
......@@ -25,8 +31,8 @@ module ProtectedRef
end
end
def protected_ref_accessible_to?(ref, user, action:)
access_levels_for_ref(ref, action: action).any? do |access_level|
def protected_ref_accessible_to?(ref, user, action:, protected_refs: nil)
access_levels_for_ref(ref, action: action, protected_refs: protected_refs).any? do |access_level|
access_level.check_access(user)
end
end
......@@ -37,8 +43,9 @@ module ProtectedRef
end
end
def access_levels_for_ref(ref, action:)
self.matching(ref).map(&:"#{action}_access_levels").flatten
def access_levels_for_ref(ref, action:, protected_refs: nil)
self.matching(ref, protected_refs: protected_refs)
.map(&:"#{action}_access_levels").flatten
end
def matching(ref_name, protected_refs: nil)
......
......@@ -236,10 +236,21 @@ class MergeRequestDiff < ActiveRecord::Base
def create_merge_request_diff_files(diffs)
rows = diffs.map.with_index do |diff, index|
diff.to_hash.merge(
diff_hash = diff.to_hash.merge(
binary: false,
merge_request_diff_id: self.id,
relative_order: index
)
# Compatibility with old diffs created with Psych.
diff_hash.tap do |hash|
diff_text = hash[:diff]
if diff_text.encoding == Encoding::BINARY && !diff_text.ascii_only?
hash[:binary] = true
hash[:diff] = [diff_text].pack('m0')
end
end
end
Gitlab::Database.bulk_insert('merge_request_diff_files', rows)
......@@ -268,9 +279,7 @@ class MergeRequestDiff < ActiveRecord::Base
st_diffs
end
elsif merge_request_diff_files.present?
merge_request_diff_files
.as_json(only: Gitlab::Git::Diff::SERIALIZE_KEYS)
.map(&:with_indifferent_access)
merge_request_diff_files.map(&:to_hash)
end
end
......
......@@ -8,4 +8,14 @@ class MergeRequestDiffFile < ActiveRecord::Base
encode_utf8(diff) if diff.respond_to?(:encoding)
end
def diff
binary? ? super.unpack('m0').first : super
end
def to_hash
keys = Gitlab::Git::Diff::SERIALIZE_KEYS - [:diff]
as_json(only: keys).merge(diff: diff).with_indifferent_access
end
end
......@@ -3,10 +3,8 @@ class JiraService < IssueTrackerService
validates :url, url: true, presence: true, if: :activated?
validates :api_url, url: true, allow_blank: true
validates :project_key, presence: true, if: :activated?
prop_accessor :username, :password, :url, :api_url, :project_key,
:jira_issue_transition_id, :title, :description
prop_accessor :username, :password, :url, :api_url, :jira_issue_transition_id, :title, :description
before_update :reset_password
......@@ -54,10 +52,6 @@ class JiraService < IssueTrackerService
@client ||= JIRA::Client.new(options)
end
def jira_project
@jira_project ||= jira_request { client.Project.find(project_key) }
end
def help
"You need to configure JIRA before enabling this service. For more details
read the
......@@ -88,18 +82,12 @@ class JiraService < IssueTrackerService
[
{ type: 'text', name: 'url', title: 'Web URL', placeholder: 'https://jira.example.com', required: true },
{ type: 'text', name: 'api_url', title: 'JIRA API URL', placeholder: 'If different from Web URL' },
{ type: 'text', name: 'project_key', placeholder: 'Project Key', required: true },
{ type: 'text', name: 'username', placeholder: '', required: true },
{ type: 'password', name: 'password', placeholder: '', required: true },
{ type: 'text', name: 'jira_issue_transition_id', placeholder: '' }
{ type: 'text', name: 'jira_issue_transition_id', title: 'Transition ID', placeholder: '' }
]
end
# URLs to redirect from Gitlab issues pages to jira issue tracker
def project_url
"#{url}/issues/?jql=project=#{project_key}"
end
def issues_url
"#{url}/browse/:id"
end
......@@ -184,7 +172,7 @@ class JiraService < IssueTrackerService
def test_settings
return unless client_url.present?
# Test settings by getting the project
jira_request { jira_project.present? }
jira_request { client.ServerInfo.all.attrs }
end
private
......
......@@ -471,8 +471,17 @@ class Repository
end
cache_method :root_ref
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/314
def exists?
refs_directory_exists?
return false unless path_with_namespace
Gitlab::GitalyClient.migrate(:repository_exists) do |enabled|
if enabled
raw_repository.exists?
else
refs_directory_exists?
end
end
end
cache_method :exists?
......@@ -1095,8 +1104,6 @@ class Repository
end
def refs_directory_exists?
return false unless path_with_namespace
File.exist?(File.join(path_to_repo, 'refs'))
end
......
class SystemNoteMetadata < ActiveRecord::Base
ICON_TYPES = %w[
commit description merge confidential visible label assignee cross_reference
title time_tracking branch milestone discussion task moved opened closed merged
title time_tracking branch milestone discussion task moved
opened closed merged duplicate
outdated
].freeze
......
module Ci
class BuildPolicy < CommitStatusPolicy
condition(:protected_action) do
next false unless @subject.action?
condition(:protected_ref) do
access = ::Gitlab::UserAccess.new(@user, project: @subject.project)
if @subject.tag?
!access.can_create_tag?(@subject.ref)
else
!access.can_merge_to_branch?(@subject.ref)
!access.can_update_branch?(@subject.ref)
end
end
rule { protected_action }.prevent :update_build
rule { protected_ref }.prevent :update_build
end
end
module Ci
class PipelinePolicy < BasePolicy
delegate { @subject.project }
condition(:protected_ref) do
access = ::Gitlab::UserAccess.new(@user, project: @subject.project)
if @subject.tag?
!access.can_create_tag?(@subject.ref)
else
!access.can_update_branch?(@subject.ref)
end
end
rule { protected_ref }.prevent :update_pipeline
end
end
......@@ -44,7 +44,7 @@ class GlobalPolicy < BasePolicy
prevent :log_in
end
rule { ~restricted_public_level }.policy do
rule { admin | ~restricted_public_level }.policy do
enable :read_users_list
end
end
......@@ -16,7 +16,8 @@ class BuildDetailsEntity < JobEntity
end
expose :path do |build|
project_merge_request_path(project, build.merge_request)
project_merge_request_path(build.merge_request.project,
build.merge_request)
end
end
......
......@@ -9,7 +9,7 @@ class DeployKeyEntity < Grape::Entity
expose :created_at
expose :updated_at
expose :projects, using: ProjectEntity do |deploy_key|
deploy_key.projects.select { |project| options[:user].can?(:read_project, project) }
deploy_key.projects.without_deleted.select { |project| options[:user].can?(:read_project, project) }
end
expose :can_edit
......
......@@ -15,12 +15,40 @@ module Ci
pipeline_schedule: schedule
)
result = validate(current_user || trigger_request.trigger.owner,
ignore_skip_ci: ignore_skip_ci,
save_on_errors: save_on_errors)
return result if result
Ci::Pipeline.transaction do
update_merge_requests_head_pipeline if pipeline.save
Ci::CreatePipelineStagesService
.new(project, current_user)
.execute(pipeline)
end
cancel_pending_pipelines if project.auto_cancel_pending_pipelines?
pipeline_created_counter.increment(source: source)
pipeline.tap(&:process!)
end
private
def validate(triggering_user, ignore_skip_ci:, save_on_errors:)
unless project.builds_enabled?
return error('Pipeline is disabled')
end
unless trigger_request || can?(current_user, :create_pipeline, project)
return error('Insufficient permissions to create a new pipeline')
unless allowed_to_trigger_pipeline?(triggering_user)
if can?(triggering_user, :create_pipeline, project)
return error("Insufficient permissions for protected ref '#{ref}'")
else
return error('Insufficient permissions to create a new pipeline')
end
end
unless branch? || tag?
......@@ -46,24 +74,29 @@ module Ci
unless pipeline.has_stage_seeds?
return error('No stages / jobs for this pipeline.')
end
end
Ci::Pipeline.transaction do
update_merge_requests_head_pipeline if pipeline.save
Ci::CreatePipelineStagesService
.new(project, current_user)
.execute(pipeline)
def allowed_to_trigger_pipeline?(triggering_user)
if triggering_user
allowed_to_create?(triggering_user)
else # legacy triggers don't have a corresponding user
!project.protected_for?(ref)
end
end
cancel_pending_pipelines if project.auto_cancel_pending_pipelines?
pipeline_created_counter.increment(source: source)
def allowed_to_create?(triggering_user)
access = Gitlab::UserAccess.new(triggering_user, project: project)
pipeline.tap(&:process!)
can?(triggering_user, :create_pipeline, project) &&
if branch?
access.can_update_branch?(ref)
elsif tag?
access.can_create_tag?(ref)
else
true # Allow it for now and we'll reject when we check ref existence
end
end
private
def update_merge_requests_head_pipeline
return unless pipeline.latest?
......@@ -113,15 +146,21 @@ module Ci
end
def branch?
project.repository.ref_exists?(Gitlab::Git::BRANCH_REF_PREFIX + ref)
return @is_branch if defined?(@is_branch)
@is_branch =
project.repository.ref_exists?(Gitlab::Git::BRANCH_REF_PREFIX + ref)
end
def tag?
project.repository.ref_exists?(Gitlab::Git::TAG_REF_PREFIX + ref)
return @is_tag if defined?(@is_tag)
@is_tag =
project.repository.ref_exists?(Gitlab::Git::TAG_REF_PREFIX + ref)
end
def ref
Gitlab::Git.ref_name(origin_ref)
@ref ||= Gitlab::Git.ref_name(origin_ref)
end
def valid_sha?
......
module Ci
class CreateTriggerRequestService
def execute(project, trigger, ref, variables = nil)
module CreateTriggerRequestService
Result = Struct.new(:trigger_request, :pipeline)
def self.execute(project, trigger, ref, variables = nil)
trigger_request = trigger.trigger_requests.create(variables: variables)
pipeline = Ci::CreatePipelineService.new(project, trigger.owner, ref: ref)
.execute(:trigger, ignore_skip_ci: true, trigger_request: trigger_request)
trigger_request if pipeline.persisted?
Result.new(trigger_request, pipeline)
end
end
end
......@@ -58,6 +58,7 @@ class IssuableBaseService < BaseService
params.delete(:assignee_ids)
params.delete(:assignee_id)
params.delete(:due_date)
params.delete(:canonical_issue_id)
end
filter_assignee(issuable)
......
......@@ -7,6 +7,14 @@ module Issues
issue_data
end
def reopen_service
Issues::ReopenService
end
def close_service
Issues::CloseService
end
private
def create_assignee_note(issue, old_assignees)
......
module Issues
class DuplicateService < Issues::BaseService
def execute(duplicate_issue, canonical_issue)
return if canonical_issue == duplicate_issue
return unless can?(current_user, :update_issue, duplicate_issue)
return unless can?(current_user, :create_note, canonical_issue)
create_issue_duplicate_note(duplicate_issue, canonical_issue)
create_issue_canonical_note(canonical_issue, duplicate_issue)
close_service.new(project, current_user, {}).execute(duplicate_issue)
end
private
def create_issue_duplicate_note(duplicate_issue, canonical_issue)
SystemNoteService.mark_duplicate_issue(duplicate_issue, duplicate_issue.project, current_user, canonical_issue)
end
def create_issue_canonical_note(canonical_issue, duplicate_issue)
SystemNoteService.mark_canonical_issue_of_duplicate(canonical_issue, canonical_issue.project, current_user, duplicate_issue)
end
end
end
......@@ -5,6 +5,7 @@ module Issues
def execute(issue)
handle_move_between_iids(issue)
filter_spam_check_params
change_issue_duplicate(issue)
update(issue)
end
......@@ -53,14 +54,6 @@ module Issues
end
end
def reopen_service
Issues::ReopenService
end
def close_service
Issues::CloseService
end
def handle_move_between_iids(issue)
return unless params[:move_between_iids]
......@@ -72,6 +65,15 @@ module Issues
issue.move_between(issue_before, issue_after)
end
def change_issue_duplicate(issue)
canonical_issue_id = params.delete(:canonical_issue_id)
canonical_issue = IssuesFinder.new(current_user).find_by(id: canonical_issue_id)
if canonical_issue
Issues::DuplicateService.new(project, current_user).execute(issue, canonical_issue)
end
end
private
def get_issue_if_allowed(project, iid)
......
......@@ -15,40 +15,48 @@ module Projects
def execute
return false unless can?(current_user, :remove_project, project)
repo_path = project.path_with_namespace
wiki_path = repo_path + '.wiki'
# Flush the cache for both repositories. This has to be done _before_
# removing the physical repositories as some expiration code depends on
# Git data (e.g. a list of branch names).
flush_caches(project, wiki_path)
flush_caches(project)
Projects::UnlinkForkService.new(project, current_user).execute
Project.transaction do
project.team.truncate
project.destroy!
unless remove_legacy_registry_tags
raise_error('Failed to remove some tags in project container registry. Please try again or contact administrator.')
end
unless remove_repository(repo_path)
raise_error('Failed to remove project repository. Please try again or contact administrator.')
end
attempt_destroy_transaction(project)
unless remove_repository(wiki_path)
raise_error('Failed to remove wiki repository. Please try again or contact administrator.')
end
end
log_info("Project \"#{project.path_with_namespace}\" was removed")
system_hook_service.execute_hooks_for(project, :destroy)
log_info("Project \"#{project.full_path}\" was removed")
true
rescue => error
attempt_rollback(project, error.message)
false
rescue Exception => error # rubocop:disable Lint/RescueException
# Project.transaction can raise Exception
attempt_rollback(project, error.message)
raise
end
private
def repo_path
project.path_with_namespace
end
def wiki_path
repo_path + '.wiki'
end
def trash_repositories!
unless remove_repository(repo_path)
raise_error('Failed to remove project repository. Please try again or contact administrator.')
end
unless remove_repository(wiki_path)
raise_error('Failed to remove wiki repository. Please try again or contact administrator.')
end
end
def remove_repository(path)
# Skip repository removal. We use this flag when remove user or group
return true if params[:skip_repo] == true
......@@ -70,6 +78,26 @@ module Projects
end
end
def attempt_rollback(project, message)
return unless project
project.update_attributes(delete_error: message, pending_delete: false)
log_error("Deletion failed on #{project.full_path} with the following message: #{message}")
end
def attempt_destroy_transaction(project)
Project.transaction do
unless remove_legacy_registry_tags
raise_error('Failed to remove some tags in project container registry. Please try again or contact administrator.')
end
trash_repositories!
project.team.truncate
project.destroy!
end
end
##
# This method makes sure that we correctly remove registry tags
# for legacy image repository (when repository path equals project path).
......@@ -96,7 +124,7 @@ module Projects
"#{path}+#{project.id}#{DELETED_FLAG}"
end
def flush_caches(project, wiki_path)
def flush_caches(project)
project.repository.before_delete
Repository.new(wiki_path, project).before_delete
......
......@@ -130,7 +130,11 @@ module Projects
end
def max_size
current_application_settings.max_pages_size.megabytes || MAX_SIZE
max_pages_size = current_application_settings.max_pages_size.megabytes
return MAX_SIZE if max_pages_size.zero?
[max_pages_size, MAX_SIZE].min
end
def tmp_path
......
......@@ -471,6 +471,24 @@ module QuickActions
end
end
desc 'Mark this issue as a duplicate of another issue'
explanation do |duplicate_reference|
"Marks this issue as a duplicate of #{duplicate_reference}."
end
params '#issue'
condition do
issuable.is_a?(Issue) &&
issuable.persisted? &&
current_user.can?(:"update_#{issuable.to_ability_name}", issuable)
end
command :duplicate do |duplicate_param|
canonical_issue = extract_references(duplicate_param, :issue).first
if canonical_issue.present?
@updates[:canonical_issue_id] = canonical_issue.id
end
end
def extract_users(params)
return [] if params.nil?
......
......@@ -552,6 +552,44 @@ module SystemNoteService
create_note(NoteSummary.new(noteable, project, author, body, action: 'moved'))
end
# Called when a Noteable has been marked as a duplicate of another Issue
#
# noteable - Noteable object
# project - Project owning noteable
# author - User performing the change
# canonical_issue - Issue that this is a duplicate of
#
# Example Note text:
#
# "marked this issue as a duplicate of #1234"
#
# "marked this issue as a duplicate of other_project#5678"
#
# Returns the created Note object
def mark_duplicate_issue(noteable, project, author, canonical_issue)
body = "marked this issue as a duplicate of #{canonical_issue.to_reference(project)}"
create_note(NoteSummary.new(noteable, project, author, body, action: 'duplicate'))
end
# Called when a Noteable has been marked as the canonical Issue of a duplicate
#
# noteable - Noteable object
# project - Project owning noteable
# author - User performing the change
# duplicate_issue - Issue that was a duplicate of this
#
# Example Note text:
#
# "marked #1234 as a duplicate of this issue"
#
# "marked other_project#5678 as a duplicate of this issue"
#
# Returns the created Note object
def mark_canonical_issue_of_duplicate(noteable, project, author, duplicate_issue)
body = "marked #{duplicate_issue.to_reference(project)} as a duplicate of this issue"
create_note(NoteSummary.new(noteable, project, author, body, action: 'duplicate'))
end
private
def notes_for_mentioner(mentioner, noteable, notes)
......
......@@ -150,7 +150,7 @@
.well-segment.well-centered
= link_to admin_groups_path do
%h3.text-center
Groups
Groups:
= number_with_delimiter(Group.count)
%hr
= link_to 'New group', new_admin_group_path, class: "btn btn-new"
......
- project = local_assigns.fetch(:project)
- return unless project.delete_error.present?
.project-deletion-failed-message.alert.alert-warning
This project was scheduled for deletion, but failed with the following message:
= project.delete_error
- project = local_assigns.fetch(:project)
- flash_message_container = show_new_nav? ? :new_global_flash : :flash_message
= content_for flash_message_container do
= render partial: 'deletion_failed', locals: { project: project }
- if current_user && can?(current_user, :download_code, project)
= render 'shared/no_ssh'
= render 'shared/no_password'
- @no_container = true
- flash_message_container = show_new_nav? ? :new_global_flash : :flash_message
= content_for flash_message_container do
- if current_user && can?(current_user, :download_code, @project)
= render 'shared/no_ssh'
= render 'shared/no_password'
= render partial: 'flash_messages', locals: { project: @project }
= render "projects/head"
= render "home_panel"
......
- @no_container = true
- page_title "Labels"
- hide_class = ''
- can_admin_label = can?(current_user, :admin_label, @project)
- if show_new_nav? && can?(current_user, :admin_label, @project)
- content_for :breadcrumbs_extra do
......@@ -12,15 +13,17 @@
%div{ class: container_class }
.top-area.adjust
.nav-text
Labels can be applied to issues and merge requests. Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging.
Labels can be applied to issues and merge requests.
- if can_admin_label
Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging.
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
- if can?(current_user, :admin_label, @project)
- if can_admin_label
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
= link_to new_project_label_path(@project), class: "btn btn-new" do
New label
.labels
- if can?(current_user, :admin_label, @project)
- if can_admin_label
-# Only show it in the first page
- hide = @available_labels.empty? || (params[:page].present? && params[:page] != '1')
.prioritized-labels{ class: ('hide' if hide) }
......@@ -33,7 +36,7 @@
- if @labels.present?
.other-labels
- if can?(current_user, :admin_label, @project)
- if can_admin_label
%h5{ class: ('hide' if hide) } Other Labels
%ul.content-list.manage-labels-list.js-other-labels
= render partial: 'shared/label', subject: @project, collection: @labels, as: :label
......
......@@ -3,7 +3,7 @@
= form_for [@project.namespace.becomes(Namespace), @project, @merge_request], url: project_new_merge_request_path(@project), method: :get, html: { class: "merge-request-form form-inline js-requires-input" } do |f|
.hide.alert.alert-danger.mr-compare-errors
.merge-request-branches.row
.merge-request-branches.js-merge-request-new-compare.row{ 'data-target-project-url': project_new_merge_request_update_branches_path(@source_project), 'data-source-branch-url': project_new_merge_request_branch_from_path(@source_project), 'data-target-branch-url': project_new_merge_request_branch_to_path(@source_project) }
.col-md-6
.panel.panel-default.panel-new-merge-request
.panel-heading
......@@ -66,10 +66,3 @@
- if @merge_request.errors.any?
= form_errors(@merge_request)
= f.submit 'Compare branches and continue', class: "btn btn-new mr-compare-btn"
:javascript
new Compare({
targetProjectUrl: "#{project_new_merge_request_update_branches_path(@source_project)}",
sourceBranchUrl: "#{project_new_merge_request_branch_from_path(@source_project)}",
targetBranchUrl: "#{project_new_merge_request_branch_to_path(@source_project)}"
});
......@@ -17,7 +17,7 @@
= f.hidden_field :target_project_id
= f.hidden_field :target_branch
.mr-compare.merge-request
.mr-compare.merge-request.js-merge-request-new-submit{ 'data-mr-submit-action': "#{j params[:tab].presence || 'new'}" }
- if @commits.empty?
.commits-empty
%h4
......@@ -50,8 +50,3 @@
.mr-loading-status
= spinner
:javascript
var merge_request = new MergeRequest({
action: "#{j params[:tab].presence || 'new'}",
});
......@@ -3,10 +3,10 @@
- page_description @merge_request.description
- page_card_attributes @merge_request.card_attributes
- content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('diff_notes')
= webpack_bundle_tag('common_vue')
= webpack_bundle_tag('diff_notes')
.merge-request{ 'data-url' => merge_request_path(@merge_request, format: :json), 'data-project-path' => project_path(@merge_request.project) }
.merge-request{ 'data-mr-action': "#{j params[:tab].presence || 'show'}", 'data-url' => merge_request_path(@merge_request, format: :json), 'data-project-path' => project_path(@merge_request.project) }
= render "projects/merge_requests/mr_title"
.merge-request-details.issuable-details{ data: { id: @merge_request.project.id } }
......@@ -15,13 +15,13 @@
- if @merge_request.source_branch_exists?
= render "projects/merge_requests/how_to_merge"
-# haml-lint:disable InlineJavaScript
:javascript
window.gl.mrWidgetData = #{serialize_issuable(@merge_request)}
#js-vue-mr-widget.mr-widget
- content_for :page_specific_javascripts do
= webpack_bundle_tag 'common_vue'
= webpack_bundle_tag 'vue_merge_request_widget'
.content-block.content-block-small.emoji-list-container
......@@ -88,10 +88,3 @@
= render "projects/commit/change", type: 'revert', commit: @merge_request.merge_commit, title: @merge_request.title
- if @merge_request.can_be_cherry_picked?
= render "projects/commit/change", type: 'cherry-pick', commit: @merge_request.merge_commit, title: @merge_request.title
:javascript
$(function () {
window.mergeRequest = new MergeRequest({
action: "#{j params[:tab].presence || 'show'}",
});
});
......@@ -72,7 +72,7 @@
%div
- if fogbugz_import_enabled?
= link_to new_import_fogbugz_path, class: 'btn import_fogbugz' do
= icon('bug', text: 'Fogbugz')
= icon('bug', text: 'FogBugz')
%div
- if gitea_import_enabled?
= link_to new_import_gitea_url, class: 'btn import_gitea' do
......
- @no_container = true
- breadcrumb_title "Project"
- @content_class = "limit-container-width" unless fluid_layout
- flash_message_container = show_new_nav? ? :new_global_flash : :flash_message
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, project_path(@project, rss_url_options), title: "#{@project.name} activity")
= content_for flash_message_container do
- if current_user && can?(current_user, :download_code, @project)
= render 'shared/no_ssh'
= render 'shared/no_password'
= render partial: 'flash_messages', locals: { project: @project }
= render "projects/head"
= render "projects/last_push"
......
- if @projects.any?
.project-item-select-holder
= project_select_tag :project_path, class: "project-item-select", data: { include_groups: local_assigns[:include_groups], order_by: 'last_activity_at' }, with_feature_enabled: local_assigns[:with_feature_enabled]
%a.btn.btn-new.new-project-item-select-button{ data: { relative_path: local_assigns[:path] } }
= project_select_tag :project_path, class: "project-item-select", data: { include_groups: local_assigns[:include_groups], order_by: 'last_activity_at', relative_path: local_assigns[:path] }, with_feature_enabled: local_assigns[:with_feature_enabled]
%a.btn.btn-new.new-project-item-select-button
= local_assigns[:label]
= icon('caret-down')
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14" height="14" viewBox="0 0 14 14">
<path d="M13 12.75v-8.5q0-0.102-0.074-0.176t-0.176-0.074h-8.5q-0.102 0-0.176 0.074t-0.074 0.176v8.5q0 0.102 0.074 0.176t0.176 0.074h8.5q0.102 0 0.176-0.074t0.074-0.176zM14 4.25v8.5q0 0.516-0.367 0.883t-0.883 0.367h-8.5q-0.516 0-0.883-0.367t-0.367-0.883v-8.5q0-0.516 0.367-0.883t0.883-0.367h8.5q0.516 0 0.883 0.367t0.367 0.883zM11 1.25v1.25h-1v-1.25q0-0.102-0.074-0.176t-0.176-0.074h-8.5q-0.102 0-0.176 0.074t-0.074 0.176v8.5q0 0.102 0.074 0.176t0.176 0.074h1.25v1h-1.25q-0.516 0-0.883-0.367t-0.367-0.883v-8.5q0-0.516 0.367-0.883t0.883-0.367h8.5q0.516 0 0.883 0.367t0.367 0.883z"></path>
</svg>
......@@ -4,5 +4,5 @@
= link_to user, title: user.name, class: "darken" do
= image_tag avatar_icon(user, 32), class: "avatar s32"
%strong= truncate(user.name, length: 40)
%br
%small.cgray= user.username
%div
%small.cgray= user.username
......@@ -6,15 +6,12 @@ class PipelineScheduleWorker
Ci::PipelineSchedule.active.where("next_run_at < ?", Time.now)
.preload(:owner, :project).find_each do |schedule|
begin
unless schedule.runnable_by_owner?
schedule.deactivate!
next
end
Ci::CreatePipelineService.new(schedule.project,
schedule.owner,
ref: schedule.ref)
pipeline = Ci::CreatePipelineService.new(schedule.project,
schedule.owner,
ref: schedule.ref)
.execute(:schedule, save_on_errors: false, schedule: schedule)
schedule.deactivate! unless pipeline.persisted?
rescue => e
Rails.logger.error "#{schedule.id}: Failed to create a scheduled pipeline: #{e.message}"
ensure
......
......@@ -3,14 +3,11 @@ class ProjectDestroyWorker
include DedicatedSidekiqQueue
def perform(project_id, user_id, params)
begin
project = Project.unscoped.find(project_id)
rescue ActiveRecord::RecordNotFound
return
end
project = Project.find(project_id)
user = User.find(user_id)
::Projects::DestroyService.new(project, user, params.symbolize_keys).execute
rescue ActiveRecord::RecordNotFound => error
logger.error("Failed to delete project (#{project_id}): #{error.message}")
end
end
---
title: Declare related resources into V4 API entities
merge_request:
author:
---
title: Added /duplicate quick action to close a duplicate issue
merge_request: 12845
author: Ryan Scott
---
title: Handle errors while a project is being deleted asynchronously.
merge_request: 11088
author:
---
title: Fix vertical alignment in firefox and safari for pipeline mini graph
merge_request:
author:
---
title: Disallow running the pipeline if ref is protected and user cannot merge the
branch or create the tag
merge_request: 11910
author:
---
title: Remove project_key from the Jira configuration
merge_request: 12050
author:
---
title: Add CSRF token verification to API
merge_request: 12154
author: Vitaliy @blackst0ne Klachkov
---
title: Added link to the MR widget that directs to the monitoring dashboard
merge_request:
author:
---
title: Remove help message about prioritized labels for non-members
merge_request: 12912
author: Takuya Noguchi
---
title: Add link to doc/api/ci/lint.md
merge_request: 12914
author: Takuya Noguchi
---
title: Pending delete projects should not show in deploy keys.
merge_request: 13088
author:
---
title: Fix margins in the mini graph for pipeline in commits box
merge_request:
author:
---
title: Fix anonymous access to public projects in groups with pending invites
merge_request:
author:
---
title: Fixes 500 error caused by pending delete projects in admin dashboard
merge_request: 13067
author:
---
title: Allow admin to read_users_list even if it's restricted
merge_request: 13066
author:
---
title: Fix creating merge request diffs when diff contains bytes that are invalid
in UTF-8
merge_request:
author:
---
title: Add instrumentation to MarkupHelper#link_to_gfm
merge_request: 13069
author:
---
title: Prevent LDAP login callback from being called with a GET request
merge_request: 13059
author:
---
title: Fix some invalid entries in PO files
merge_request: 13032
author:
---
title: Fix cross site request protection when logging in as a regular user when LDAP
is enabled
merge_request: 13049
author:
---
title: Free up some top level words, reject top level groups named like files in the
public folder
merge_request: 12932
author:
---
title: Support custom directory in gitlab:backup:create task
merge_request: 12984
author: Markus Koller
---
title: Fix job merge request link to a forked source project
merge_request: 12965
author:
---
title: Handle maximum pages artifacts size correctly
merge_request: 13072
author:
---
title: Fix editing project with container images present
merge_request: 13028
author:
---
title: Fix pipeline_schedules pages throwing error 500 (when ref is empty)
merge_request: 12983
author:
---
title: Fixed issue boards sidebar close icon size
title: Add LDAP SSL certificate verification option
merge_request:
author:
---
title: Improve redirect route query performance
merge_request: 13062
author:
---
title: Fixed duplicate new milestone buttons when new navigation is turned on
merge_request:
author:
---
title: Fix sizing of custom header logo in new navigation
merge_request:
author:
---
title: Ensure filesystem metrics test files are deleted
merge_request:
author:
---
title: Fix bug causing metrics files to be truncated
merge_request: 35420
author:
---
title: Enable gitaly_post_upload_pack by default
merge_request: 13078
author:
---
title: Fix the /projects/:id/repository/branches endpoint to handle dots in the branch
name when the project full patch contains a `/`
merge_request: 13115
author:
---
title: Add author_id & assignee_id param to /issues API
merge_request: 13004
author:
......@@ -228,7 +228,8 @@ production: &base
# ==========================
## LDAP settings
# You can inspect a sample of the LDAP users with login access by running:
# You can test connections and inspect a sample of the LDAP users with login
# access by running:
# bundle exec rake gitlab:ldap:check RAILS_ENV=production
ldap:
enabled: false
......@@ -251,13 +252,45 @@ production: &base
# Example: 'Paris' or 'Acme, Ltd.'
label: 'LDAP'
# Example: 'ldap.mydomain.com'
host: '_your_ldap_server'
port: 389
uid: 'sAMAccountName'
method: 'plain' # "tls" or "ssl" or "plain"
# This port is an example, it is sometimes different but it is always an integer and not a string
port: 389 # usually 636 for SSL
uid: 'sAMAccountName' # This should be the attribute, not the value that maps to uid.
# Examples: 'america\\momo' or 'CN=Gitlab Git,CN=Users,DC=mydomain,DC=com'
bind_dn: '_the_full_dn_of_the_user_you_will_bind_with'
password: '_the_password_of_the_bind_user'
# Encryption method. The "method" key is deprecated in favor of
# "encryption".
#
# Examples: "start_tls" or "simple_tls" or "plain"
#
# Deprecated values: "tls" was replaced with "start_tls" and "ssl" was
# replaced with "simple_tls".
#
encryption: 'plain'
# Enables SSL certificate verification if encryption method is
# "start_tls" or "simple_tls". (Defaults to false for backward-
# compatibility)
verify_certificates: false
# Specifies the path to a file containing a PEM-format CA certificate,
# e.g. if you need to use an internal CA.
#
# Example: '/etc/ca.pem'
#
ca_cert: ''
# Specifies the SSL version for OpenSSL to use, if the OpenSSL default
# is not appropriate.
#
# Example: 'TLSv1_1'
#
ssl_version: ''
# Set a timeout, in seconds, for LDAP queries. This helps avoid blocking
# a request if the LDAP server becomes unresponsive.
# A value of 0 means there is no timeout.
......@@ -286,17 +319,20 @@ production: &base
# Base where we can search for users
#
# Ex. ou=People,dc=gitlab,dc=example
# Ex. 'ou=People,dc=gitlab,dc=example' or 'DC=mydomain,DC=com'
#
base: ''
# Filter LDAP users
#
# Format: RFC 4515 http://tools.ietf.org/search/rfc4515
# Format: RFC 4515 https://tools.ietf.org/search/rfc4515
# Ex. (employeeType=developer)
#
# Note: GitLab does not support omniauth-ldap's custom filter syntax.
#
# Example for getting only specific users:
# '(&(objectclass=user)(|(samaccountname=momo)(samaccountname=toto)))'
#
user_filter: ''
# LDAP attributes that GitLab will use to create an account for the LDAP user.
......@@ -674,7 +710,7 @@ test:
host: 127.0.0.1
port: 3890
uid: 'uid'
method: 'plain' # "tls" or "ssl" or "plain"
encryption: 'plain' # "start_tls" or "simple_tls" or "plain"
base: 'dc=example,dc=com'
user_filter: ''
group_base: 'ou=groups,dc=example,dc=com'
......
......@@ -145,6 +145,24 @@ if Settings.ldap['enabled'] || Rails.env.test?
server['attributes'] = {} if server['attributes'].nil?
server['provider_name'] ||= "ldap#{key}".downcase
server['provider_class'] = OmniAuth::Utils.camelize(server['provider_name'])
# For backwards compatibility
server['encryption'] ||= server['method']
server['encryption'] = 'simple_tls' if server['encryption'] == 'ssl'
server['encryption'] = 'start_tls' if server['encryption'] == 'tls'
# Certificates are not verified for backwards compatibility.
# This default should be flipped to true in 9.5.
if server['verify_certificates'].nil?
server['verify_certificates'] = false
message = <<-MSG.strip_heredoc
LDAP SSL certificate verification is disabled for backwards-compatibility.
Please add the "verify_certificates" option to gitlab.yml for each LDAP
server. Certificate verification will be enabled by default in GitLab 9.5.
MSG
Rails.logger.warn(message)
end
end
end
......@@ -441,10 +459,6 @@ Settings.backup['pg_schema'] = nil
Settings.backup['path'] = Settings.absolute(Settings.backup['path'] || "tmp/backups/")
Settings.backup['archive_permissions'] ||= 0600
Settings.backup['upload'] ||= Settingslogic.new({ 'remote_directory' => nil, 'connection' => nil })
# Convert upload connection settings to use symbol keys, to make Fog happy
if Settings.backup['upload']['connection']
Settings.backup['upload']['connection'] = Hash[Settings.backup['upload']['connection'].map { |k, v| [k.to_sym, v] }]
end
Settings.backup['upload']['multipart_chunk_size'] ||= 104857600
Settings.backup['upload']['encryption'] ||= nil
Settings.backup['upload']['storage_class'] ||= nil
......
......@@ -6,7 +6,7 @@ Prometheus::Client.configure do |config|
config.initial_mmap_file_size = 4 * 1024
config.multiprocess_files_dir = ENV['prometheus_multiproc_dir']
if Rails.env.development? && Rails.env.test?
if Rails.env.development? || Rails.env.test?
config.multiprocess_files_dir ||= Rails.root.join('tmp/prometheus_multiproc_dir')
end
end
......@@ -114,6 +114,9 @@ def instrument_classes(instrumentation)
# This is a Rails scope so we have to instrument it manually.
instrumentation.instrument_method(Project, :visible_to_user)
# Needed for https://gitlab.com/gitlab-org/gitlab-ce/issues/34509
instrumentation.instrument_method(MarkupHelper, :link_to_gfm)
# Needed for https://gitlab.com/gitlab-org/gitlab-ce/issues/30224#note_32306159
instrumentation.instrument_instance_method(MergeRequestDiff, :load_commits)
end
......
if defined?(GrapeRouteHelpers)
module GrapeRouteHelpers
class DecoratedRoute
# GrapeRouteHelpers gem tries to parse the versions
# from a string, not supporting Grape `version` array definition.
#
# Without the following fix, we get this on route helpers generation:
#
# => undefined method `scan' for ["v3", "v4"]
#
# 2.0.0 implementation of this method:
#
# ```
# def route_versions
# version_pattern = /[^\[",\]\s]+/
# if route_version
# route_version.scan(version_pattern)
# else
# [nil]
# end
# end
# ```
def route_versions
return [nil] if route_version.nil? || route_version.empty?
if route_version.is_a?(String)
version_pattern = /[^\[",\]\s]+/
route_version.scan(version_pattern)
else
route_version
end
end
end
end
end
......@@ -16,7 +16,7 @@ OmniAuth.config.allowed_request_methods = [:post]
# In case of auto sign-in, the GET method is used (users don't get to click on a button)
OmniAuth.config.allowed_request_methods << :get if Gitlab.config.omniauth.auto_sign_in_with_provider.present?
OmniAuth.config.before_request_phase do |env|
OmniAuth::RequestForgeryProtection.call(env)
Gitlab::RequestForgeryProtection.call(env)
end
if Gitlab.config.omniauth.enabled
......
API::API.logger Rails.logger
mount API::API => '/api'
mount API::API => '/'
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment