Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-09-02 18:10:54 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-09-02 18:10:54 +0300
commit8e3523281051490ff696bfd85bea1195c046c87c (patch)
treee44c77aa24136950679151ae70ad6e186987602a /app
parente2d4c85dec083d517822e3a21165cd373b162d9b (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js5
-rw-r--r--app/controllers/clusters/clusters_controller.rb5
-rw-r--r--app/controllers/concerns/authenticates_with_two_factor.rb24
-rw-r--r--app/controllers/concerns/enforces_two_factor_authentication.rb18
-rw-r--r--app/controllers/omniauth_callbacks_controller.rb11
-rw-r--r--app/controllers/profiles/active_sessions_controller.rb1
-rw-r--r--app/controllers/profiles/two_factor_auths_controller.rb4
-rw-r--r--app/controllers/sessions_controller.rb13
-rw-r--r--app/finders/ci/auth_job_finder.rb56
-rw-r--r--app/finders/user_recent_events_finder.rb12
-rw-r--r--app/graphql/mutations/boards/lists/base.rb2
-rw-r--r--app/graphql/mutations/boards/lists/create.rb9
-rw-r--r--app/graphql/mutations/snippets/base.rb2
-rw-r--r--app/models/active_session.rb13
-rw-r--r--app/models/aws/role.rb1
-rw-r--r--app/models/clusters/applications/runner.rb2
-rw-r--r--app/models/concerns/discussion_on_diff.rb2
-rw-r--r--app/models/concerns/resolvable_discussion.rb1
-rw-r--r--app/models/diff_discussion.rb1
-rw-r--r--app/models/discussion.rb1
-rw-r--r--app/models/member.rb2
-rw-r--r--app/models/user.rb7
-rw-r--r--app/services/applications/create_service.rb11
-rw-r--r--app/services/auth/container_registry_authentication_service.rb1
-rw-r--r--app/services/branches/delete_service.rb2
-rw-r--r--app/services/ci/pipeline_trigger_service.rb7
-rw-r--r--app/services/clusters/aws/authorize_role_service.rb16
-rw-r--r--app/services/members/destroy_service.rb33
-rw-r--r--app/services/projects/update_remote_mirror_service.rb4
-rw-r--r--app/views/profiles/active_sessions/_active_session.html.haml2
-rw-r--r--app/views/projects/issues/service_desk.html.haml2
31 files changed, 211 insertions, 59 deletions
diff --git a/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js b/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js
index 9bea7aa7b04..d2ac80fa190 100644
--- a/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js
+++ b/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js
@@ -86,6 +86,11 @@ export const conditions = flattenDeep(
value: __('Any'),
},
{
+ url: 'author_username=support-bot',
+ tokenKey: 'author',
+ value: 'support-bot',
+ },
+ {
url: 'milestone_title=None',
tokenKey: 'milestone',
value: __('None'),
diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb
index b6d5eb7e5c0..7006c23321c 100644
--- a/app/controllers/clusters/clusters_controller.rb
+++ b/app/controllers/clusters/clusters_controller.rb
@@ -38,8 +38,7 @@ class Clusters::ClustersController < Clusters::BaseController
def new
if params[:provider] == 'aws'
- @aws_role = current_user.aws_role || Aws::Role.new
- @aws_role.ensure_role_external_id!
+ @aws_role = Aws::Role.create_or_find_by!(user: current_user)
@instance_types = load_instance_types.to_json
elsif params[:provider] == 'gcp'
@@ -274,7 +273,7 @@ class Clusters::ClustersController < Clusters::BaseController
end
def aws_role_params
- params.require(:cluster).permit(:role_arn, :role_external_id)
+ params.require(:cluster).permit(:role_arn)
end
def generate_gcp_authorize_url
diff --git a/app/controllers/concerns/authenticates_with_two_factor.rb b/app/controllers/concerns/authenticates_with_two_factor.rb
index 4b4bcc8d37e..2cc51c65c26 100644
--- a/app/controllers/concerns/authenticates_with_two_factor.rb
+++ b/app/controllers/concerns/authenticates_with_two_factor.rb
@@ -22,6 +22,8 @@ module AuthenticatesWithTwoFactor
return handle_locked_user(user) unless user.can?(:log_in)
session[:otp_user_id] = user.id
+ session[:user_updated_at] = user.updated_at
+
setup_u2f_authentication(user)
render 'devise/sessions/two_factor'
end
@@ -39,6 +41,7 @@ module AuthenticatesWithTwoFactor
def authenticate_with_two_factor
user = self.resource = find_user
return handle_locked_user(user) unless user.can?(:log_in)
+ return handle_changed_user(user) if user_changed?(user)
if user_params[:otp_attempt].present? && session[:otp_user_id]
authenticate_with_two_factor_via_otp(user)
@@ -63,12 +66,14 @@ module AuthenticatesWithTwoFactor
def clear_two_factor_attempt!
session.delete(:otp_user_id)
+ session.delete(:user_updated_at)
+ session.delete(:challenge)
end
def authenticate_with_two_factor_via_otp(user)
if valid_otp_attempt?(user)
# Remove any lingering user data from login
- session.delete(:otp_user_id)
+ clear_two_factor_attempt!
remember_me(user) if user_params[:remember_me] == '1'
user.save!
@@ -85,8 +90,7 @@ module AuthenticatesWithTwoFactor
def authenticate_with_two_factor_via_u2f(user)
if U2fRegistration.authenticate(user, u2f_app_id, user_params[:device_response], session[:challenge])
# Remove any lingering user data from login
- session.delete(:otp_user_id)
- session.delete(:challenge)
+ clear_two_factor_attempt!
remember_me(user) if user_params[:remember_me] == '1'
sign_in(user, message: :two_factor_authenticated, event: :authentication)
@@ -113,4 +117,18 @@ module AuthenticatesWithTwoFactor
end
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ def handle_changed_user(user)
+ clear_two_factor_attempt!
+
+ redirect_to new_user_session_path, alert: _('An error occurred. Please sign in again.')
+ end
+
+ # If user has been updated since we validated the password,
+ # the password might have changed.
+ def user_changed?(user)
+ return false unless session[:user_updated_at]
+
+ user.updated_at != session[:user_updated_at]
+ end
end
diff --git a/app/controllers/concerns/enforces_two_factor_authentication.rb b/app/controllers/concerns/enforces_two_factor_authentication.rb
index f1dd46648f1..02082f81598 100644
--- a/app/controllers/concerns/enforces_two_factor_authentication.rb
+++ b/app/controllers/concerns/enforces_two_factor_authentication.rb
@@ -29,12 +29,11 @@ module EnforcesTwoFactorAuthentication
end
def two_factor_authentication_required?
- Gitlab::CurrentSettings.require_two_factor_authentication? ||
- current_user.try(:require_two_factor_authentication_from_group?)
+ two_factor_verifier.two_factor_authentication_required?
end
def current_user_requires_two_factor?
- current_user && !current_user.temp_oauth_email? && !current_user.two_factor_enabled? && !skip_two_factor?
+ two_factor_verifier.current_user_needs_to_setup_two_factor? && !skip_two_factor?
end
# rubocop: disable CodeReuse/ActiveRecord
@@ -43,7 +42,7 @@ module EnforcesTwoFactorAuthentication
if Gitlab::CurrentSettings.require_two_factor_authentication?
global.call
else
- groups = current_user.expanded_groups_requiring_two_factor_authentication.reorder(name: :asc)
+ groups = current_user.source_groups_of_two_factor_authentication_requirement.reorder(name: :asc)
group.call(groups)
end
end
@@ -51,14 +50,11 @@ module EnforcesTwoFactorAuthentication
# rubocop: enable CodeReuse/ActiveRecord
def two_factor_grace_period
- periods = [Gitlab::CurrentSettings.two_factor_grace_period]
- periods << current_user.two_factor_grace_period if current_user.try(:require_two_factor_authentication_from_group?)
- periods.min
+ two_factor_verifier.two_factor_grace_period
end
def two_factor_grace_period_expired?
- date = current_user.otp_grace_period_started_at
- date && (date + two_factor_grace_period.hours) < Time.current
+ two_factor_verifier.two_factor_grace_period_expired?
end
def two_factor_skippable?
@@ -70,6 +66,10 @@ module EnforcesTwoFactorAuthentication
def skip_two_factor?
session[:skip_two_factor] && session[:skip_two_factor] > Time.current
end
+
+ def two_factor_verifier
+ @two_factor_verifier ||= Gitlab::Auth::TwoFactorAuthVerifier.new(current_user) # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ end
end
EnforcesTwoFactorAuthentication.prepend_if_ee('EE::EnforcesTwoFactorAuthentication')
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index 6a393405e4d..a558b01f0c6 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -50,12 +50,6 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
redirect_unverified_saml_initiation
end
- def omniauth_error
- @provider = params[:provider]
- @error = params[:error]
- render 'errors/omniauth_error', layout: "oauth_error", status: :unprocessable_entity
- end
-
def cas3
ticket = params['ticket']
if ticket
@@ -205,9 +199,10 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def fail_login(user)
log_failed_login(user.username, oauth['provider'])
- error_message = user.errors.full_messages.to_sentence
+ @provider = Gitlab::Auth::OAuth::Provider.label_for(params[:action])
+ @error = user.errors.full_messages.to_sentence
- redirect_to omniauth_error_path(oauth['provider'], error: error_message)
+ render 'errors/omniauth_error', layout: "oauth_error", status: :unprocessable_entity
end
def fail_auth0_login
diff --git a/app/controllers/profiles/active_sessions_controller.rb b/app/controllers/profiles/active_sessions_controller.rb
index f409193aefc..d9ec3195fd1 100644
--- a/app/controllers/profiles/active_sessions_controller.rb
+++ b/app/controllers/profiles/active_sessions_controller.rb
@@ -7,6 +7,7 @@ class Profiles::ActiveSessionsController < Profiles::ApplicationController
def destroy
ActiveSession.destroy_with_public_id(current_user, params[:id])
+ current_user.forget_me!
respond_to do |format|
format.html { redirect_to profile_active_sessions_url, status: :found }
diff --git a/app/controllers/profiles/two_factor_auths_controller.rb b/app/controllers/profiles/two_factor_auths_controller.rb
index a88c5ca4fa1..f600c34ca75 100644
--- a/app/controllers/profiles/two_factor_auths_controller.rb
+++ b/app/controllers/profiles/two_factor_auths_controller.rb
@@ -4,7 +4,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
skip_before_action :check_two_factor_requirement
def show
- unless current_user.otp_secret
+ unless current_user.two_factor_enabled?
current_user.otp_secret = User.generate_otp_secret(32)
end
@@ -38,6 +38,8 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
def create
if current_user.validate_and_consume_otp!(params[:pin_code])
+ ActiveSession.destroy_all_but_current(current_user, session)
+
Users::UpdateService.new(current_user, user: current_user, otp_required_for_login: true).execute! do |user|
@codes = user.generate_otp_backup_codes!
end
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index baf7a05f8ba..5da2bafbcb3 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -8,6 +8,7 @@ class SessionsController < Devise::SessionsController
include Recaptcha::Verify
include RendersLdapServers
include KnownSignIn
+ include Gitlab::Utils::StrongMemoize
skip_before_action :check_two_factor_requirement, only: [:destroy]
skip_before_action :check_password_expiration, only: [:destroy]
@@ -199,10 +200,14 @@ class SessionsController < Devise::SessionsController
end
def find_user
- if session[:otp_user_id]
- User.find(session[:otp_user_id])
- elsif user_params[:login]
- User.by_login(user_params[:login])
+ strong_memoize(:find_user) do
+ if session[:otp_user_id] && user_params[:login]
+ User.by_id_and_login(session[:otp_user_id], user_params[:login]).first
+ elsif session[:otp_user_id]
+ User.find(session[:otp_user_id])
+ elsif user_params[:login]
+ User.by_login(user_params[:login])
+ end
end
end
diff --git a/app/finders/ci/auth_job_finder.rb b/app/finders/ci/auth_job_finder.rb
new file mode 100644
index 00000000000..aee7dd16341
--- /dev/null
+++ b/app/finders/ci/auth_job_finder.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+module Ci
+ class AuthJobFinder
+ AuthError = Class.new(StandardError)
+ NotRunningJobError = Class.new(AuthError)
+ ErasedJobError = Class.new(AuthError)
+ DeletedProjectError = Class.new(AuthError)
+
+ def initialize(token:)
+ @token = token
+ end
+
+ def execute!
+ find_job_by_token.tap do |job|
+ next unless job
+
+ validate_job!(job)
+ end
+ end
+
+ def execute
+ execute!
+ rescue AuthError
+ end
+
+ private
+
+ attr_reader :token, :require_running, :raise_on_missing
+
+ def find_job_by_token
+ ::Ci::Build.find_by_token(token)
+ end
+
+ def validate_job!(job)
+ validate_running_job!(job)
+ validate_job_not_erased!(job)
+ validate_project_presence!(job)
+
+ true
+ end
+
+ def validate_running_job!(job)
+ raise NotRunningJobError, 'Job is not running' unless job.running?
+ end
+
+ def validate_job_not_erased!(job)
+ raise ErasedJobError, 'Job has been erased!' if job.erased?
+ end
+
+ def validate_project_presence!(job)
+ if job.project.nil? || job.project.pending_delete?
+ raise DeletedProjectError, 'Project has been deleted!'
+ end
+ end
+ end
+end
diff --git a/app/finders/user_recent_events_finder.rb b/app/finders/user_recent_events_finder.rb
index 3f2e813d381..f376b26ab9c 100644
--- a/app/finders/user_recent_events_finder.rb
+++ b/app/finders/user_recent_events_finder.rb
@@ -6,6 +6,7 @@
# WARNING: does not consider project feature visibility!
# - user: The user for which to load the events
# - params:
+# - limit: Number of items that to be returned. Defaults to 20 and limited to 100.
# - offset: The page of events to return
class UserRecentEventsFinder
prepend FinderWithCrossProjectAccess
@@ -16,7 +17,8 @@ class UserRecentEventsFinder
attr_reader :current_user, :target_user, :params
- LIMIT = 20
+ DEFAULT_LIMIT = 20
+ MAX_LIMIT = 100
def initialize(current_user, target_user, params = {})
@current_user = current_user
@@ -31,7 +33,7 @@ class UserRecentEventsFinder
recent_events(params[:offset] || 0)
.joins(:project)
.with_associations
- .limit_recent(params[:limit].presence || LIMIT, params[:offset])
+ .limit_recent(limit, params[:offset])
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -59,4 +61,10 @@ class UserRecentEventsFinder
def projects
target_user.project_interactions.to_sql
end
+
+ def limit
+ return DEFAULT_LIMIT unless params[:limit].present?
+
+ [params[:limit].to_i, MAX_LIMIT].min
+ end
end
diff --git a/app/graphql/mutations/boards/lists/base.rb b/app/graphql/mutations/boards/lists/base.rb
index 34b271ba3b8..d244d6bf8dd 100644
--- a/app/graphql/mutations/boards/lists/base.rb
+++ b/app/graphql/mutations/boards/lists/base.rb
@@ -8,7 +8,7 @@ module Mutations
argument :board_id, ::Types::GlobalIDType[::Board],
required: true,
- description: 'The Global ID of the issue board to mutate'
+ description: 'Global ID of the issue board to mutate'
field :list,
Types::BoardListType,
diff --git a/app/graphql/mutations/boards/lists/create.rb b/app/graphql/mutations/boards/lists/create.rb
index 4f545709ee9..3fe1052315f 100644
--- a/app/graphql/mutations/boards/lists/create.rb
+++ b/app/graphql/mutations/boards/lists/create.rb
@@ -12,7 +12,7 @@ module Mutations
argument :label_id, ::Types::GlobalIDType[::Label],
required: false,
- description: 'ID of an existing label'
+ description: 'Global ID of an existing label'
def ready?(**args)
if args.slice(*mutually_exclusive_args).size != 1
@@ -39,6 +39,7 @@ module Mutations
private
+ # Overridden in EE
def authorize_list_type_resource!(board, params)
return unless params[:label_id]
@@ -57,13 +58,15 @@ module Mutations
create_list_service.execute(board)
end
+ # Overridden in EE
def create_list_params(args)
params = args.slice(*mutually_exclusive_args).with_indifferent_access
- params[:label_id] = GitlabSchema.parse_gid(params[:label_id]).model_id if params[:label_id]
+ params[:label_id] &&= ::GitlabSchema.parse_gid(params[:label_id], expected_type: ::Label).model_id
params
end
+ # Overridden in EE
def mutually_exclusive_args
[:backlog, :label_id]
end
@@ -71,3 +74,5 @@ module Mutations
end
end
end
+
+Mutations::Boards::Lists::Create.prepend_if_ee('::EE::Mutations::Boards::Lists::Create')
diff --git a/app/graphql/mutations/snippets/base.rb b/app/graphql/mutations/snippets/base.rb
index c8cc721b2e0..023f876d035 100644
--- a/app/graphql/mutations/snippets/base.rb
+++ b/app/graphql/mutations/snippets/base.rb
@@ -11,7 +11,7 @@ module Mutations
private
def find_object(id:)
- GitlabSchema.object_from_id(id)
+ GitlabSchema.object_from_id(id, expected_type: ::Snippet)
end
def authorized_resource?(snippet)
diff --git a/app/models/active_session.rb b/app/models/active_session.rb
index be07c221f32..4908290e06b 100644
--- a/app/models/active_session.rb
+++ b/app/models/active_session.rb
@@ -105,6 +105,19 @@ class ActiveSession
end
end
+ def self.destroy_all_but_current(user, current_session)
+ session_ids = not_impersonated(user)
+ session_ids.reject! { |session| session.current?(current_session) } if current_session
+
+ Gitlab::Redis::SharedState.with do |redis|
+ destroy_sessions(redis, user, session_ids.map(&:session_id)) if session_ids.any?
+ end
+ end
+
+ def self.not_impersonated(user)
+ list(user).reject(&:is_impersonated)
+ end
+
def self.key_name(user_id, session_id = '*')
"#{Gitlab::Redis::SharedState::USER_SESSIONS_NAMESPACE}:#{user_id}:#{session_id}"
end
diff --git a/app/models/aws/role.rb b/app/models/aws/role.rb
index 54132be749d..7d34665082d 100644
--- a/app/models/aws/role.rb
+++ b/app/models/aws/role.rb
@@ -9,6 +9,7 @@ module Aws
validates :role_external_id, uniqueness: true, length: { in: 1..64 }
validates :role_arn,
length: 1..2048,
+ allow_nil: true,
format: {
with: Gitlab::Regex.aws_arn_regex,
message: Gitlab::Regex.aws_arn_regex_message
diff --git a/app/models/clusters/applications/runner.rb b/app/models/clusters/applications/runner.rb
index f33d54544ca..4983de83800 100644
--- a/app/models/clusters/applications/runner.rb
+++ b/app/models/clusters/applications/runner.rb
@@ -3,7 +3,7 @@
module Clusters
module Applications
class Runner < ApplicationRecord
- VERSION = '0.20.0'
+ VERSION = '0.20.1'
self.table_name = 'clusters_applications_runners'
diff --git a/app/models/concerns/discussion_on_diff.rb b/app/models/concerns/discussion_on_diff.rb
index 8542c48f366..40891073738 100644
--- a/app/models/concerns/discussion_on_diff.rb
+++ b/app/models/concerns/discussion_on_diff.rb
@@ -13,14 +13,12 @@ module DiscussionOnDiff
:diff_line,
:active?,
:created_at_diff?,
-
to: :first_note
delegate :file_path,
:blob,
:highlighted_diff_lines,
:diff_lines,
-
to: :diff_file,
allow_nil: true
end
diff --git a/app/models/concerns/resolvable_discussion.rb b/app/models/concerns/resolvable_discussion.rb
index 5174ae05d15..3e1e5faee54 100644
--- a/app/models/concerns/resolvable_discussion.rb
+++ b/app/models/concerns/resolvable_discussion.rb
@@ -31,7 +31,6 @@ module ResolvableDiscussion
delegate :resolved_at,
:resolved_by,
:resolved_by_push?,
-
to: :last_resolved_note,
allow_nil: true
end
diff --git a/app/models/diff_discussion.rb b/app/models/diff_discussion.rb
index f9e2f00b9f3..6806008d676 100644
--- a/app/models/diff_discussion.rb
+++ b/app/models/diff_discussion.rb
@@ -16,7 +16,6 @@ class DiffDiscussion < Discussion
:diff_note_positions,
:on_text?,
:on_image?,
-
to: :first_note
def legacy_diff_discussion?
diff --git a/app/models/discussion.rb b/app/models/discussion.rb
index adcb2217d85..793cdb5dece 100644
--- a/app/models/discussion.rb
+++ b/app/models/discussion.rb
@@ -24,7 +24,6 @@ class Discussion
:system_note_with_references_visible_for?,
:resource_parent,
:save,
-
to: :first_note
def declarative_policy_delegate
diff --git a/app/models/member.rb b/app/models/member.rb
index a27076b49d7..1913df61614 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -76,6 +76,8 @@ class Member < ApplicationRecord
scope :request, -> { where.not(requested_at: nil) }
scope :non_request, -> { where(requested_at: nil) }
+ scope :not_accepted_invitations_by_user, -> (user) { invite.where(invite_accepted_at: nil, created_by: user) }
+
scope :has_access, -> { active.where('access_level > 0') }
scope :guests, -> { active.where(access_level: GUEST) }
diff --git a/app/models/user.rb b/app/models/user.rb
index 355a174ba9a..7574f0865a0 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -364,6 +364,7 @@ class User < ApplicationRecord
scope :order_oldest_sign_in, -> { reorder(Gitlab::Database.nulls_last_order('current_sign_in_at', 'ASC')) }
scope :order_recent_last_activity, -> { reorder(Gitlab::Database.nulls_last_order('last_activity_on', 'DESC')) }
scope :order_oldest_last_activity, -> { reorder(Gitlab::Database.nulls_first_order('last_activity_on', 'ASC')) }
+ scope :by_id_and_login, ->(id, login) { where(id: id).where('username = LOWER(:login) OR email = LOWER(:login)', login: login) }
def preferred_language
read_attribute('preferred_language') ||
@@ -887,6 +888,12 @@ class User < ApplicationRecord
all_expanded_groups.where(require_two_factor_authentication: true)
end
+ def source_groups_of_two_factor_authentication_requirement
+ Gitlab::ObjectHierarchy.new(expanded_groups_requiring_two_factor_authentication)
+ .all_objects
+ .where(id: groups)
+ end
+
# rubocop: disable CodeReuse/ServiceClass
def refresh_authorized_projects
Users::RefreshAuthorizedProjectsService.new(self).execute
diff --git a/app/services/applications/create_service.rb b/app/services/applications/create_service.rb
index 500db1e172a..92500fbc254 100644
--- a/app/services/applications/create_service.rb
+++ b/app/services/applications/create_service.rb
@@ -11,7 +11,16 @@ module Applications
# EE would override and use `request` arg
def execute(request)
- Doorkeeper::Application.create(params)
+ @application = Doorkeeper::Application.new(params)
+
+ unless params[:scopes].present?
+ @application.errors.add(:base, _("Scopes can't be blank"))
+
+ return @application
+ end
+
+ @application.save
+ @application
end
end
end
diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb
index 44a434f4402..831a25a637e 100644
--- a/app/services/auth/container_registry_authentication_service.rb
+++ b/app/services/auth/container_registry_authentication_service.rb
@@ -132,6 +132,7 @@ module Auth
def can_access?(requested_project, requested_action)
return false unless requested_project.container_registry_enabled?
+ return false if requested_project.repository_access_level == ::ProjectFeature::DISABLED
case requested_action
when 'pull'
diff --git a/app/services/branches/delete_service.rb b/app/services/branches/delete_service.rb
index 9bd5b343448..6efbdd161a1 100644
--- a/app/services/branches/delete_service.rb
+++ b/app/services/branches/delete_service.rb
@@ -26,7 +26,7 @@ module Branches
message: 'Failed to remove branch',
http_status: 400)
end
- rescue Gitlab::Git::PreReceiveError => ex
+ rescue Gitlab::Git::PreReceiveError, Gitlab::Git::CommandError => ex
ServiceResponse.error(message: ex.message, http_status: 400)
end
diff --git a/app/services/ci/pipeline_trigger_service.rb b/app/services/ci/pipeline_trigger_service.rb
index 37b9b4c362c..d9f41b7040e 100644
--- a/app/services/ci/pipeline_trigger_service.rb
+++ b/app/services/ci/pipeline_trigger_service.rb
@@ -10,6 +10,9 @@ module Ci
elsif job_from_token
create_pipeline_from_job(job_from_token)
end
+
+ rescue Ci::AuthJobFinder::AuthError => e
+ error(e.message, 401)
end
private
@@ -41,8 +44,6 @@ module Ci
# this check is to not leak the presence of the project if user cannot read it
return unless can?(job.user, :read_project, project)
- return error("400 Job has to be running", 400) unless job.running?
-
pipeline = Ci::CreatePipelineService.new(project, job.user, ref: params[:ref])
.execute(:pipeline, ignore_skip_ci: true) do |pipeline|
source = job.sourced_pipelines.build(
@@ -64,7 +65,7 @@ module Ci
def job_from_token
strong_memoize(:job) do
- Ci::Build.find_by_token(params[:token].to_s)
+ Ci::AuthJobFinder.new(token: params[:token].to_s).execute!
end
end
diff --git a/app/services/clusters/aws/authorize_role_service.rb b/app/services/clusters/aws/authorize_role_service.rb
index fb620f77b9f..2712a4b05bb 100644
--- a/app/services/clusters/aws/authorize_role_service.rb
+++ b/app/services/clusters/aws/authorize_role_service.rb
@@ -9,6 +9,7 @@ module Clusters
ERRORS = [
ActiveRecord::RecordInvalid,
+ ActiveRecord::RecordNotFound,
Clusters::Aws::FetchCredentialsService::MissingRoleError,
::Aws::Errors::MissingCredentialsError,
::Aws::STS::Errors::ServiceError
@@ -20,7 +21,8 @@ module Clusters
end
def execute
- @role = create_or_update_role!
+ ensure_role_exists!
+ update_role_arn!
Response.new(:ok, credentials)
rescue *ERRORS => e
@@ -33,14 +35,12 @@ module Clusters
attr_reader :role, :params
- def create_or_update_role!
- if role = user.aws_role
- role.update!(params)
+ def ensure_role_exists!
+ @role = ::Aws::Role.find_by_user_id!(user.id)
+ end
- role
- else
- user.create_aws_role!(params)
- end
+ def update_role_arn!
+ role.update!(params)
end
def credentials
diff --git a/app/services/members/destroy_service.rb b/app/services/members/destroy_service.rb
index fdd43260521..8cad065e6cc 100644
--- a/app/services/members/destroy_service.rb
+++ b/app/services/members/destroy_service.rb
@@ -18,6 +18,7 @@ module Members
end
delete_subresources(member) unless skip_subresources
+ delete_project_invitations_by(member) unless skip_subresources
enqueue_delete_todos(member)
enqueue_unassign_issuables(member) if unassign_issuables
@@ -39,24 +40,48 @@ module Members
delete_project_members(member)
delete_subgroup_members(member)
+ delete_invited_members(member)
end
def delete_project_members(member)
groups = member.group.self_and_descendants
- ProjectMember.in_namespaces(groups).with_user(member.user).each do |project_member|
- self.class.new(current_user).execute(project_member, skip_authorization: @skip_auth)
- end
+ destroy_project_members(ProjectMember.in_namespaces(groups).with_user(member.user))
end
def delete_subgroup_members(member)
groups = member.group.descendants
- GroupMember.of_groups(groups).with_user(member.user).each do |group_member|
+ destroy_group_members(GroupMember.of_groups(groups).with_user(member.user))
+ end
+
+ def delete_invited_members(member)
+ groups = member.group.self_and_descendants
+
+ destroy_group_members(GroupMember.of_groups(groups).not_accepted_invitations_by_user(member.user))
+
+ destroy_project_members(ProjectMember.in_namespaces(groups).not_accepted_invitations_by_user(member.user))
+ end
+
+ def destroy_project_members(members)
+ members.each do |project_member|
+ self.class.new(current_user).execute(project_member, skip_authorization: @skip_auth)
+ end
+ end
+
+ def destroy_group_members(members)
+ members.each do |group_member|
self.class.new(current_user).execute(group_member, skip_authorization: @skip_auth, skip_subresources: true)
end
end
+ def delete_project_invitations_by(member)
+ return unless member.is_a?(ProjectMember) && member.user && member.project
+
+ members_to_delete = member.project.members.not_accepted_invitations_by_user(member.user)
+ destroy_project_members(members_to_delete)
+ end
+
def can_destroy_member?(member)
can?(current_user, destroy_member_permission(member), member)
end
diff --git a/app/services/projects/update_remote_mirror_service.rb b/app/services/projects/update_remote_mirror_service.rb
index fe2610f89fb..7961f689259 100644
--- a/app/services/projects/update_remote_mirror_service.rb
+++ b/app/services/projects/update_remote_mirror_service.rb
@@ -7,6 +7,10 @@ module Projects
def execute(remote_mirror, tries)
return success unless remote_mirror.enabled?
+ if Gitlab::UrlBlocker.blocked_url?(CGI.unescape(Gitlab::UrlSanitizer.sanitize(remote_mirror.url)))
+ return error("The remote mirror URL is invalid.")
+ end
+
update_mirror(remote_mirror)
success
diff --git a/app/views/profiles/active_sessions/_active_session.html.haml b/app/views/profiles/active_sessions/_active_session.html.haml
index 9ae75fe6b8e..c4b3fa80d75 100644
--- a/app/views/profiles/active_sessions/_active_session.html.haml
+++ b/app/views/profiles/active_sessions/_active_session.html.haml
@@ -27,6 +27,6 @@
- unless is_current_session
.float-right
- = link_to profile_active_session_path(active_session.public_id), data: { confirm: _('Are you sure? The device will be signed out of GitLab.') }, method: :delete, class: "btn btn-danger gl-ml-3" do
+ = link_to profile_active_session_path(active_session.public_id), data: { confirm: _('Are you sure? The device will be signed out of GitLab and all remember me tokens revoked.') }, method: :delete, class: "btn btn-danger gl-ml-3" do
%span.sr-only= _('Revoke')
= _('Revoke')
diff --git a/app/views/projects/issues/service_desk.html.haml b/app/views/projects/issues/service_desk.html.haml
index bd260bdf143..65580a94cd0 100644
--- a/app/views/projects/issues/service_desk.html.haml
+++ b/app/views/projects/issues/service_desk.html.haml
@@ -7,7 +7,7 @@
- support_bot_attrs = { service_desk_enabled: @project.service_desk_enabled?, **UserSerializer.new.represent(User.support_bot) }.to_json
-- data_endpoint = "#{expose_path(api_v4_projects_issues_path(id: @project.id))}?author_id=#{User.support_bot.id}"
+- data_endpoint = "#{expose_path(api_v4_projects_issues_path(id: @project.id))}?author_username=#{User.support_bot.username}"
%div{ class: "js-service-desk-issues service-desk-issues", data: { support_bot: support_bot_attrs, service_desk_meta: service_desk_meta(@project) } }
.top-area