...
 
Commits (102)
......@@ -19,7 +19,7 @@
dependencies:
- setup-test-env
services:
- docker:stable-dind
- docker:19.03.0-dind
variables:
NODE_ENV: "production"
RAILS_ENV: "production"
......
......@@ -35,7 +35,7 @@
<<: *review-base
image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-alpine
services:
- docker:stable-dind
- docker:19.03.0-dind
tags:
- gitlab-org
- docker
......@@ -261,6 +261,7 @@ danger-review:
except:
refs:
- master
- /^[\d-]+-stable(-ee)?$/
variables:
- $CI_COMMIT_REF_NAME =~ /^ce-to-ee-.*/
- $CI_COMMIT_REF_NAME =~ /.*-stable(-ee)?-prepare-.*/
......
This diff is collapsed.
......@@ -206,9 +206,6 @@ gem 'redis-rails', '~> 5.0.2'
gem 'redis', '~> 3.2'
gem 'connection_pool', '~> 2.0'
# Discord integration
gem 'discordrb-webhooks-blackst0ne', '~> 3.3', require: false
# HipChat integration
gem 'hipchat', '~> 1.5.0'
......
......@@ -194,8 +194,6 @@ GEM
rotp (~> 2.0)
diff-lcs (1.3)
diffy (3.1.0)
discordrb-webhooks-blackst0ne (3.3.0)
rest-client (~> 2.0)
docile (1.3.1)
domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0)
......@@ -1089,7 +1087,6 @@ DEPENDENCIES
devise (~> 4.6)
devise-two-factor (~> 3.0.0)
diffy (~> 3.1.0)
discordrb-webhooks-blackst0ne (~> 3.3)
doorkeeper (~> 4.3)
doorkeeper-openid_connect (~> 1.5)
ed25519 (~> 1.2)
......
......@@ -14,7 +14,6 @@ export default {
},
data() {
return {
loading: false,
pages: [],
};
},
......@@ -37,17 +36,18 @@ export default {
return pdfjsLib
.getDocument(this.document)
.then(this.renderPages)
.then(() => this.$emit('pdflabload'))
.catch(error => this.$emit('pdflaberror', error))
.then(() => {
this.loading = false;
.then(pages => {
this.pages = pages;
this.$emit('pdflabload');
})
.catch(error => {
this.$emit('pdflaberror', error);
});
},
renderPages(pdf) {
const pagePromises = [];
this.loading = true;
for (let num = 1; num <= pdf.numPages; num += 1) {
pagePromises.push(pdf.getPage(num).then(p => this.pages.push(p)));
pagePromises.push(pdf.getPage(num));
}
return Promise.all(pagePromises);
},
......@@ -59,8 +59,8 @@ export default {
<div v-if="hasPDF" class="pdf-viewer">
<page
v-for="(page, index) in pages"
v-if="page"
:key="index"
:v-if="!loading"
:page="page"
:number="index + 1"
/>
......
......@@ -39,7 +39,9 @@ export default {
.then(() => {
this.rendering = false;
})
.catch(error => this.$emit('pdflaberror', error));
.catch(error => {
this.$emit('pdflaberror', error);
});
},
};
</script>
......
......@@ -127,6 +127,7 @@
.section-header ~ .section.line {
margin-left: $gl-padding;
display: block;
}
}
......
......@@ -90,7 +90,7 @@ module UploadsActions
return unless uploader = build_uploader
upload_paths = uploader.upload_paths(params[:filename])
upload = Upload.find_by(uploader: uploader_class.to_s, path: upload_paths)
upload = Upload.find_by(model: model, uploader: uploader_class.to_s, path: upload_paths)
upload&.build_uploader
end
# rubocop: enable CodeReuse/ActiveRecord
......
......@@ -28,6 +28,9 @@ class GroupsController < Groups::ApplicationController
before_action :user_actions, only: [:show]
before_action :validate_name, only: [:create, :update, :transfer]
skip_cross_project_access_check :index, :new, :create, :edit, :update,
:destroy, :projects
# When loading show as an atom feed, we render events that could leak cross
......@@ -223,6 +226,19 @@ class GroupsController < Groups::ApplicationController
end
end
def validate_name
group = Group.new(group_params)
unless !group.path || group.path.empty? || group.path.length > 4 || current_user.admin?
flash.now[:alert] = 'Path must have at least a length of 5.'
if action_name == 'update'
render action: 'edit'
else
@group = group
render action: 'new'
end
end
end
def build_canonical_path(group)
return group_path(group) if action_name == 'show' # root group path
......
......@@ -5,6 +5,7 @@ class PasswordsController < Devise::PasswordsController
before_action :resource_from_email, only: [:create]
before_action :check_password_authentication_available, only: [:create]
before_action :prevent_cas_reset, only: [:create]
before_action :throttle_reset, only: [:create]
# rubocop: disable CodeReuse/ActiveRecord
......@@ -55,6 +56,13 @@ class PasswordsController < Devise::PasswordsController
alert: _("Password authentication is unavailable.")
end
def prevent_cas_reset
return unless resource && resource.cas_user?
redirect_to after_sending_reset_password_instructions_path_for(resource_name),
alert: "Cannot reset password for CAS user."
end
def throttle_reset
return unless resource && resource.recently_sent_password_reset?
......
......@@ -8,20 +8,6 @@ class Profiles::AccountsController < Profiles::ApplicationController
end
# rubocop: disable CodeReuse/ActiveRecord
def unlink
provider = params[:provider]
identity = current_user.identities.find_by(provider: provider)
return render_404 unless identity
if unlink_provider_allowed?(provider)
identity.destroy
else
flash[:alert] = _("You are not allowed to unlink your primary login account")
end
redirect_to profile_account_path
end
# rubocop: enable CodeReuse/ActiveRecord
private
......
......@@ -3,7 +3,8 @@
class Projects::BadgesController < Projects::ApplicationController
layout 'project_settings'
before_action :authorize_admin_project!, only: [:index]
before_action :no_cache_headers, except: [:index]
before_action :no_cache_headers, only: [:pipeline, :coverage]
before_action :authorize_read_build!, only: [:pipeline, :coverage]
def pipeline
pipeline_status = Gitlab::Badge::Pipeline::Status
......
......@@ -49,7 +49,7 @@ class Projects::BranchesController < Projects::ApplicationController
branches = BranchesFinder.new(repository, params.permit(names: [])).execute
Gitlab::GitalyClient.allow_n_plus_1_calls do
render json: branches.to_h { |branch| [branch.name, service.call(branch)] }
render json: branches.map { |branch| [branch.name, service.call(branch)] }.to_h
end
end
end
......
......@@ -45,7 +45,7 @@ class Projects::MergeRequests::ApplicationController < Projects::ApplicationCont
def set_pipeline_variables
@pipelines =
if can?(current_user, :read_pipeline, @project)
if can?(current_user, :read_pipeline, @merge_request.source_project)
@merge_request.all_pipelines
else
Ci::Pipeline.none
......
......@@ -82,7 +82,8 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
end
def pipelines
@pipelines = @merge_request.all_pipelines.page(params[:page]).per(30)
set_pipeline_variables
@pipelines = @pipelines.page(params[:page]).per(30)
Gitlab::PollingInterval.set_header(response, interval: 10_000)
......
......@@ -4,7 +4,7 @@ class Projects::TriggersController < Projects::ApplicationController
before_action :authorize_admin_build!
before_action :authorize_manage_trigger!, except: [:index, :create]
before_action :authorize_admin_trigger!, only: [:edit, :update]
before_action :trigger, only: [:take_ownership, :edit, :update, :destroy]
before_action :trigger, only: [:edit, :update, :destroy]
layout 'project_settings'
......@@ -24,16 +24,6 @@ class Projects::TriggersController < Projects::ApplicationController
redirect_to project_settings_ci_cd_path(@project, anchor: 'js-pipeline-triggers')
end
def take_ownership
if trigger.update(owner: current_user)
flash[:notice] = _('Trigger was re-assigned.')
else
flash[:alert] = _('You could not take ownership of trigger.')
end
redirect_to project_settings_ci_cd_path(@project, anchor: 'js-pipeline-triggers')
end
def edit
end
......
......@@ -69,7 +69,7 @@ class BranchesFinder
return branches unless names
branch_names = names.to_set
branches.filter do |branch|
branches.select do |branch|
branch_names.include?(branch.name)
end
end
......
......@@ -400,7 +400,7 @@ module ProjectsHelper
snippets: :read_project_snippet,
settings: :admin_project,
builds: :read_build,
clusters: :read_cluster,
#clusters: :read_cluster,
serverless: :read_cluster,
error_tracking: :read_sentry_issue,
labels: :read_label,
......@@ -462,11 +462,7 @@ module ProjectsHelper
end
def default_clone_protocol
if allowed_protocols_present?
enabled_protocol
else
extra_default_clone_protocol
end
extra_default_clone_protocol
end
def extra_default_clone_protocol
......
......@@ -13,6 +13,8 @@ module SubmoduleHelper
end
def submodule_links_for_url(submodule_item_id, url, repository)
return [nil, nil] unless url
if url == '.' || url == './'
url = File.join(Gitlab.config.gitlab.url, repository.project.full_path)
end
......@@ -34,8 +36,8 @@ module SubmoduleHelper
project.sub!(/\.git\z/, '')
if self_url?(url, namespace, project)
[namespace_project_path(namespace, project),
namespace_project_tree_path(namespace, project, submodule_item_id)]
[url_helpers.namespace_project_path(namespace, project),
url_helpers.namespace_project_tree_path(namespace, project, submodule_item_id)]
elsif relative_self_url?(url)
relative_self_links(url, submodule_item_id, repository.project)
elsif github_dot_com_url?(url)
......@@ -99,8 +101,8 @@ module SubmoduleHelper
begin
[
namespace_project_path(target_namespace_path, submodule_base),
namespace_project_tree_path(target_namespace_path, submodule_base, commit)
url_helpers.namespace_project_path(target_namespace_path, submodule_base),
url_helpers.namespace_project_tree_path(target_namespace_path, submodule_base, commit)
]
rescue ActionController::UrlGenerationError
[nil, nil]
......@@ -118,4 +120,8 @@ module SubmoduleHelper
rescue URI::InvalidURIError
nil
end
def url_helpers
Gitlab::Routing.url_helpers
end
end
# frozen_string_literal: true
class DeviseMailer < Devise::Mailer
default from: "#{Gitlab.config.gitlab.email_display_name} <#{Gitlab.config.gitlab.email_from}>"
default reply_to: Gitlab.config.gitlab.email_reply_to
default from: proc { default_sender_address.format }
default reply_to: proc { default_reply_to_address.format }
layout 'mailer/devise'
......@@ -17,4 +17,16 @@ class DeviseMailer < Devise::Mailer
subject.join(' | ')
end
def default_sender_address
address = Mail::Address.new(Gitlab.config.gitlab.email_from)
address.display_name = Gitlab.config.gitlab.email_display_name
address
end
def default_reply_to_address
address = Mail::Address.new(Gitlab.config.gitlab.email_reply_to)
address.display_name = Gitlab.config.gitlab.email_display_name
address
end
end
......@@ -9,12 +9,10 @@ module ProjectAPICompatibility
end
def auto_devops_enabled=(value)
self.build_auto_devops if self.auto_devops&.enabled.nil?
self.auto_devops.update! enabled: value
(auto_devops || build_auto_devops).enabled = value
end
def auto_devops_deploy_strategy=(value)
self.build_auto_devops if self.auto_devops&.enabled.nil?
self.auto_devops.update! deploy_strategy: value
(auto_devops || build_auto_devops).deploy_strategy = value
end
end
......@@ -53,6 +53,7 @@ class Group < Namespace
validate :visibility_level_allowed_by_sub_groups
validate :visibility_level_allowed_by_parent
validates :variables, variable_duplicates: true
validates :path, format: { without: /\A([a-zA-Z]{4}[0-9]{2}|hg[0-9]+)\z/, message: "must not match the format of THM usernames" }
validates :two_factor_grace_period, presence: true, numericality: { greater_than_or_equal_to: 0 }
......
......@@ -752,7 +752,7 @@ class MergeRequest < ApplicationRecord
end
def check_mergeability
MergeRequests::MergeabilityCheckService.new(self).execute
MergeRequests::MergeabilityCheckService.new(self).execute(retry_lease: false)
end
# rubocop: enable CodeReuse/ServiceClass
......
......@@ -22,7 +22,7 @@ class PagesDomain < ApplicationRecord
validate :validate_pages_domain
validate :validate_matching_key, if: ->(domain) { domain.certificate.present? || domain.key.present? }
validate :validate_intermediates, if: ->(domain) { domain.certificate.present? }
validate :validate_intermediates, if: ->(domain) { domain.certificate.present? && domain.certificate_changed? }
attr_encrypted :key,
mode: :per_attribute_iv_and_salt,
......
......@@ -137,7 +137,6 @@ class Project < ApplicationRecord
# Project services
has_one :campfire_service
has_one :discord_service
has_one :drone_ci_service
has_one :emails_on_push_service
has_one :pipelines_email_service
......@@ -277,7 +276,7 @@ class Project < ApplicationRecord
has_many :project_deploy_tokens
has_many :deploy_tokens, through: :project_deploy_tokens
has_one :auto_devops, class_name: 'ProjectAutoDevops'
has_one :auto_devops, class_name: 'ProjectAutoDevops', inverse_of: :project, autosave: true
has_many :custom_attributes, class_name: 'ProjectCustomAttribute'
has_many :project_badges, class_name: 'ProjectBadge'
......@@ -344,6 +343,7 @@ class Project < ApplicationRecord
inclusion: { in: ->(_object) { Gitlab.config.repositories.storages.keys } }
validates :variables, variable_duplicates: { scope: :environment_scope }
validates :bfg_object_map, file_size: { maximum: :max_attachment_size }
validates :path, format: { without: /\A([a-zA-Z]{4}[0-9]{2}|hg[0-9]+)\z/, message: "must not match the format of THM usernames" }
# Scopes
scope :pending_delete, -> { where(pending_delete: true) }
......@@ -1869,16 +1869,24 @@ class Project < ApplicationRecord
end
def append_or_update_attribute(name, value)
old_values = public_send(name.to_s) # rubocop:disable GitlabSecurity/PublicSend
if Project.reflect_on_association(name).try(:macro) == :has_many
# if this is 1-to-N relation, update the parent object
value.each do |item|
item.update!(
Project.reflect_on_association(name).foreign_key => id)
end
# force to drop relation cache
public_send(name).reset # rubocop:disable GitlabSecurity/PublicSend
if Project.reflect_on_association(name).try(:macro) == :has_many && old_values.any?
update_attribute(name, old_values + value)
# succeeded
true
else
# if this is another relation or attribute, update just object
update_attribute(name, value)
end
rescue ActiveRecord::RecordNotSaved => e
handle_update_attribute_error(e, value)
rescue ActiveRecord::RecordInvalid => e
raise e, "Failed to set #{name}: #{e.message}"
end
# Tries to set repository as read_only, checking for existing Git transfers in progress beforehand
......@@ -2267,18 +2275,6 @@ class Project < ApplicationRecord
ContainerRepository.build_root_repository(self).has_tags?
end
def handle_update_attribute_error(ex, value)
if ex.message.start_with?('Failed to replace')
if value.respond_to?(:each)
invalid = value.detect(&:invalid?)
raise ex, ([ex.message] + invalid.errors.full_messages).join(' ') if invalid
end
end
raise ex
end
def fetch_branch_allows_collaboration(user, branch_name = nil)
return false unless user
......
......@@ -5,7 +5,7 @@ class ProjectAutoDevops < ApplicationRecord
ignore_column :domain
belongs_to :project
belongs_to :project, inverse_of: :auto_devops
enum deploy_strategy: {
continuous: 0,
......
# frozen_string_literal: true
require "discordrb/webhooks"
class DiscordService < ChatNotificationService
def title
s_("DiscordService|Discord Notifications")
end
def description
s_("DiscordService|Receive event notifications in Discord")
end
def self.to_param
"discord"
end
def help
"This service sends notifications about project events to Discord channels.<br />
To set up this service:
<ol>
<li><a href='https://support.discordapp.com/hc/en-us/articles/228383668-Intro-to-Webhooks'>Setup a custom Incoming Webhook</a>.</li>
<li>Paste the <strong>Webhook URL</strong> into the field below.</li>
<li>Select events below to enable notifications.</li>
</ol>"
end
def event_field(event)
# No-op.
end
def default_channel_placeholder
# No-op.
end
def self.supported_events
%w[push issue confidential_issue merge_request note confidential_note tag_push
pipeline wiki_page]
end
def default_fields
[
{ type: "text", name: "webhook", placeholder: "e.g. https://discordapp.com/api/webhooks/…" },
{ type: "checkbox", name: "notify_only_broken_pipelines" },
{ type: "checkbox", name: "notify_only_default_branch" }
]
end
private
def notify(message, opts)
client = Discordrb::Webhooks::Client.new(url: webhook)
client.execute do |builder|
builder.content = message.pretext
end
end
def custom_data(data)
super(data).merge(markdown: true)
end
end
......@@ -35,6 +35,8 @@ class SlashCommandsService < Service
chat_user = find_chat_user(params)
if chat_user&.user
return Gitlab::SlashCommands::Presenters::Access.new.access_denied unless chat_user.user.can?(:use_slash_commands)
Gitlab::SlashCommands::Command.new(project, chat_user, params).execute
else
url = authorize_chat_name_url(params)
......
......@@ -251,7 +251,6 @@ class Service < ApplicationRecord
bugzilla
campfire
custom_issue_tracker
discord
drone_ci
emails_on_push
external_wiki
......
......@@ -836,11 +836,11 @@ class User < ApplicationRecord
end
def allow_password_authentication_for_web?
Gitlab::CurrentSettings.password_authentication_enabled_for_web? && !ldap_user? && !ultraauth_user?
Gitlab::CurrentSettings.password_authentication_enabled_for_web? && !ldap_user? && !cas_user? && !ultraauth_user?
end
def allow_password_authentication_for_git?
Gitlab::CurrentSettings.password_authentication_enabled_for_git? && !ldap_user? && !ultraauth_user?
Gitlab::CurrentSettings.password_authentication_enabled_for_git? && !ldap_user? && !cas_user? && !ultraauth_user?
end
def can_change_username?
......@@ -932,6 +932,14 @@ class User < ApplicationRecord
@ldap_identity ||= identities.find_by(["provider LIKE ?", "ldap%"])
end
def cas_user?
identities.exists?(["provider = ? AND extern_uid IS NOT NULL", "cas3"])
end
def cas_identity
@cas_identity ||= identities.find_by(["provider = ?", "cas3"])
end
def project_deploy_keys
DeployKey.unscoped.in_projects(authorized_projects.pluck(:id)).distinct(:id)
end
......
......@@ -33,6 +33,7 @@ class GlobalPolicy < BasePolicy
enable :access_git
enable :receive_notifications
enable :use_quick_actions
enable :use_slash_commands
end
rule { blocked | internal }.policy do
......@@ -40,6 +41,7 @@ class GlobalPolicy < BasePolicy
prevent :access_api
prevent :access_git
prevent :receive_notifications
prevent :use_slash_commands
end
rule { required_terms_not_accepted }.policy do
......@@ -57,6 +59,7 @@ class GlobalPolicy < BasePolicy
rule { access_locked }.policy do
prevent :log_in
prevent :use_slash_commands
end
rule { ~(anonymous & restricted_public_level) }.policy do
......
......@@ -256,6 +256,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
end
def autodevops_anchor_data(show_auto_devops_callout: false)
return
if current_user && can?(current_user, :admin_pipeline, project) && repository.gitlab_ci_yml.blank? && !show_auto_devops_callout
if auto_devops_enabled?
AnchorData.new(false,
......@@ -275,6 +276,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
end
def kubernetes_cluster_anchor_data
return
if current_user && can?(current_user, :create_cluster, project)
if clusters.empty?
......
......@@ -16,9 +16,14 @@ class IssueEntity < IssuableEntity
expose :discussion_locked
expose :assignees, using: API::Entities::UserBasic
expose :due_date
expose :moved_to_id
expose :project_id
expose :moved_to_id do |issue|
if issue.moved_to_id.present? && can?(request.current_user, :read_issue, issue.moved_to)
issue.moved_to_id
end
end
expose :web_url do |issue|
project_issue_path(issue.project, issue)
end
......
......@@ -11,15 +11,18 @@ module MergeRequests
# https://gitlab.com/gitlab-org/gitlab-ce/issues/53658
merge_quick_actions_into_params!(merge_request, only: [:target_branch])
merge_request.merge_params['force_remove_source_branch'] = params.delete(:force_remove_source_branch) if params.has_key?(:force_remove_source_branch)
merge_request.assign_attributes(params)
# Assign the projects first so we can use policies for `filter_params`
merge_request.author = current_user
merge_request.source_project = find_source_project
merge_request.target_project = find_target_project
filter_params(merge_request)
merge_request.assign_attributes(params.to_h.compact)
merge_request.compare_commits = []
merge_request.source_project = find_source_project
merge_request.target_project = find_target_project
merge_request.target_branch = find_target_branch
merge_request.can_be_created = projects_and_branches_valid?
ensure_milestone_available(merge_request)
merge_request.target_branch = find_target_branch
merge_request.can_be_created = projects_and_branches_valid?
# compare branches only if branches are valid, otherwise
# compare_branches may raise an error
......@@ -50,12 +53,14 @@ module MergeRequests
to: :merge_request
def find_source_project
source_project = project_from_params(:source_project)
return source_project if source_project.present? && can?(current_user, :create_merge_request_from, source_project)
project
end
def find_target_project
target_project = project_from_params(:target_project)
return target_project if target_project.present? && can?(current_user, :create_merge_request_in, target_project)
target_project = project.default_merge_request_target
......@@ -65,6 +70,17 @@ module MergeRequests
project
end
def project_from_params(param_name)
project_from_params = params.delete(param_name)
id_param_name = :"#{param_name}_id"
if project_from_params.nil? && params[id_param_name]
project_from_params = Project.find_by_id(params.delete(id_param_name))
end
project_from_params
end
def find_target_branch
target_branch || target_project.default_branch
end
......
......@@ -3,6 +3,7 @@
module MergeRequests
class MergeabilityCheckService < ::BaseService
include Gitlab::Utils::StrongMemoize
include Gitlab::ExclusiveLeaseHelpers
delegate :project, to: :@merge_request
delegate :repository, to: :project
......@@ -21,13 +22,35 @@ module MergeRequests
# where we need the current state of the merge ref in repository, the `recheck`
# argument is required.
#
# retry_lease - Concurrent calls wait for at least 10 seconds until the
# lease is granted (other process finishes running). Returns an error
# ServiceResponse if the lease is not granted during this time.
#
# Returns a ServiceResponse indicating merge_status is/became can_be_merged
# and the merge-ref is synced. Success in case of being/becoming mergeable,
# error otherwise.
def execute(recheck: false)
def execute(recheck: false, retry_lease: true)
return ServiceResponse.error(message: 'Invalid argument') unless merge_request
return ServiceResponse.error(message: 'Unsupported operation') if Gitlab::Database.read_only?
return check_mergeability(recheck) unless merge_ref_auto_sync_lock_enabled?
in_write_lock(retry_lease: retry_lease) do |retried|
# When multiple calls are waiting for the same lock (retry_lease),
# it's possible that when granted, the MR status was already updated for
# that object, therefore we reset if there was a lease retry.
merge_request.reset if retried
check_mergeability(recheck)
end
rescue FailedToObtainLockError => error
ServiceResponse.error(message: error.message)
end
private
attr_reader :merge_request
def check_mergeability(recheck)
recheck! if recheck
update_merge_status
......@@ -46,9 +69,21 @@ module MergeRequests
ServiceResponse.success(payload: payload)
end
private
# It's possible for this service to send concurrent requests to Gitaly in order
# to "git update-ref" the same ref. Therefore we handle a light exclusive
# lease here.
#
def in_write_lock(retry_lease:, &block)
lease_key = "mergeability_check:#{merge_request.id}"
attr_reader :merge_request
lease_opts = {
ttl: 1.minute,
retries: retry_lease ? 10 : 0,
sleep_sec: retry_lease ? 1.second : 0
}
in_lock(lease_key, lease_opts, &block)
end
def payload
strong_memoize(:payload) do
......@@ -116,5 +151,9 @@ module MergeRequests
def merge_ref_auto_sync_enabled?
Feature.enabled?(:merge_ref_auto_sync, project, default_enabled: true)
end
def merge_ref_auto_sync_lock_enabled?
Feature.enabled?(:merge_ref_auto_sync_lock, project, default_enabled: true)
end
end
end
......@@ -67,10 +67,6 @@ class FileUploader < GitlabUploader
SecureRandom.hex
end
def self.extract_dynamic_path(path)
DYNAMIC_PATH_PATTERN.match(path)
end
def upload_paths(identifier)
[
File.join(secret, identifier),
......@@ -145,7 +141,7 @@ class FileUploader < GitlabUploader
return if apply_context!(value.uploader_context)
# fallback to the regex based extraction
if matches = self.class.extract_dynamic_path(value.path)
if matches = DYNAMIC_PATH_PATTERN.match(value.path)
@secret = matches[:secret]
@identifier = matches[:identifier]
end
......
......@@ -35,7 +35,7 @@ module RecordsUploads
end
def readd_upload
uploads.where(path: upload_path).delete_all
uploads.where(model: model, path: upload_path).delete_all
upload.delete if upload
self.upload = build_upload.tap(&:save!)
......
= render "dashboard/projects", projects: @projects
.prepend-top-20
= render 'shared/promo'
- page_title "Sign in"
#signin-container
- if omniauth_enabled? && devise_mapping.omniauthable? && button_based_providers_enabled?
%div.append-bottom-default
= render 'devise/shared/omniauth_box'
#signin-container.prepend-top-15
- if form_based_providers.any?
= render 'devise/shared/tabs_ldap'
- else
......@@ -17,7 +21,3 @@
- if !password_authentication_enabled_for_web? && !ldap_enabled? && !(omniauth_enabled? && devise_mapping.omniauthable?)
%div
No authentication methods configured.
- if omniauth_enabled? && devise_mapping.omniauthable? && button_based_providers_enabled?
.clearfix
= render 'devise/shared/omniauth_box'
.omniauth-container.prepend-top-15
.omniauth-container
%label.label-bold.d-block
Sign in with
- providers = enabled_button_based_providers
......
......@@ -7,8 +7,8 @@
%h1
= default_brand_title
- if user_signed_in?
%span= link_to_version
= version_status_badge
%span= Gitlab::VERSION + '-thm'
%small= link_to Gitlab.revision, namespace_project_commits_path('projects.thm.de', 'gitlab', Gitlab.revision)
%hr
- unless Gitlab::CurrentSettings.help_page_hide_commercial_content?
......
......@@ -78,7 +78,7 @@
%li.nav-item
%div
- sign_in_text = allow_signup? ? _('Sign in / Register') : _('Sign in')
= link_to sign_in_text, new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in'
= link_to "Sign in", omniauth_authorize_path(:user, :cas3), method: :post, class: 'btn btn-sign-in', "data-no-turbolink" => "true"
%button.navbar-toggler.d-block.d-sm-none{ type: 'button' }
%span.sr-only= _('Toggle navigation')
......
......@@ -41,12 +41,6 @@
= link_to applications_profile_path do
%strong.fly-out-top-item-name
= _('Applications')
= nav_link(controller: :chat_names) do
= link_to profile_chat_names_path do
.nav-icon-container
= sprite_icon('comment')
%span.nav-item-name
= _('Chat')
%ul.sidebar-sub-level-items.is-fly-out-only
= nav_link(controller: :chat_names, html_options: { class: "fly-out-top-item" } ) do
= link_to profile_chat_names_path do
......@@ -74,7 +68,7 @@
= link_to profile_emails_path do
%strong.fly-out-top-item-name
= _('Emails')
- if current_user.allow_password_authentication?
- if current_user.allow_password_authentication? && !current_user.cas_user?
= nav_link(controller: :passwords) do
= link_to edit_profile_password_path do
.nav-icon-container
......
......@@ -274,19 +274,6 @@
= render_if_exists 'layouts/nav/sidebar/project_feature_flags_link'
- if project_nav_tab? :container_registry
= nav_link(controller: %w[projects/registry/repositories]) do
= link_to project_container_registry_index_path(@project), class: 'shortcuts-container-registry' do
.nav-icon-container
= sprite_icon('disk')
%span.nav-item-name
= _('Registry')
%ul.sidebar-sub-level-items.is-fly-out-only
= nav_link(controller: %w[projects/registry/repositories], html_options: { class: "fly-out-top-item" } ) do
= link_to project_container_registry_index_path(@project) do
%strong.fly-out-top-item-name
= _('Registry')
= render_if_exists 'layouts/nav/sidebar/project_packages_link'
- if project_nav_tab? :wiki
......
- if project_nav_tab? :container_registry
= nav_link controller: :repositories do
= link_to project_container_registry_index_path(@project) do
.nav-icon-container
= sprite_icon('package')
%span.nav-item-name
= _('Packages')
%ul.sidebar-sub-level-items
= nav_link(controller: :repositories, html_options: { class: "fly-out-top-item" } ) do
= link_to project_container_registry_index_path(@project) do
%strong.fly-out-top-item-name
= _('Packages')
%li.divider.fly-out-top-item
= nav_link controller: :repositories do
= link_to project_container_registry_index_path(@project), class: 'shortcuts-container-registry', title: _('Container Registry') do
%span= _('Container Registry')
......@@ -8,28 +8,22 @@
.row.prepend-top-default
.col-lg-4.profile-settings-sidebar
%h4.prepend-top-0
= s_('Profiles|Two-Factor Authentication')
%p
= s_("Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)")
.col-lg-8
%p
#{_('Status')}: #{current_user.two_factor_enabled? ? _('Enabled') : _('Disabled')}
- if current_user.two_factor_enabled?
= link_to _('Manage two-factor authentication'), profile_two_factor_auth_path, class: 'btn btn-info'
- else
.append-bottom-10
= link_to _('Enable two-factor authentication'), profile_two_factor_auth_path, class: 'btn btn-success'
%hr
- if display_providers_on_profile?
- if !current_user.cas_user?
.row.prepend-top-default
.col-lg-4.profile-settings-sidebar
%h4.prepend-top-0
= s_('Profiles|Social sign-in')
= s_('Profiles|Two-Factor Authentication')
%p
= s_('Profiles|Activate signin with one of the following services')
= s_("Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)")
.col-lg-8
= render 'providers', providers: button_based_providers, group_saml_identities: local_assigns[:group_saml_identities]
%p
#{_('Status')}: #{current_user.two_factor_enabled? ? _('Enabled') : _('Disabled')}
- if current_user.two_factor_enabled?
= link_to _('Manage two-factor authentication'), profile_two_factor_auth_path, class: 'btn btn-info'
- else
.append-bottom-10
= link_to _('Enable two-factor authentication'), profile_two_factor_auth_path, class: 'btn btn-success'
%hr
- if current_user.can_change_username?
.row.prepend-top-default
...