diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-08-05 18:10:10 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-08-05 18:10:10 +0000 |
commit | ea4766228b5536c83f1917d6058be913472ffa2d (patch) | |
tree | 5ebf5ea0f996be6c6908e6b631b72c33bc13e997 /app | |
parent | 4b64dc27ae5bac20dec888431c236fef2bfdc449 (diff) | |
download | gitlab-ce-ea4766228b5536c83f1917d6058be913472ffa2d.tar.gz |
Add latest changes from gitlab-org/gitlab@13-2-stable-ee
Diffstat (limited to 'app')
15 files changed, 166 insertions, 179 deletions
diff --git a/app/assets/javascripts/jobs/components/environments_block.vue b/app/assets/javascripts/jobs/components/environments_block.vue index c78738221f1..9166c13a4fb 100644 --- a/app/assets/javascripts/jobs/components/environments_block.vue +++ b/app/assets/javascripts/jobs/components/environments_block.vue @@ -1,11 +1,15 @@ <script> -import { escape, isEmpty } from 'lodash'; +import { isEmpty } from 'lodash'; import CiIcon from '~/vue_shared/components/ci_icon.vue'; -import { sprintf, __ } from '../../locale'; +import { __ } from '../../locale'; +import { GlSprintf, GlLink } from '@gitlab/ui'; export default { + creatingEnvironment: 'creating', components: { CiIcon, + GlSprintf, + GlLink, }, props: { deploymentStatus: { @@ -31,7 +35,7 @@ export default { return this.outOfDateEnvironmentMessage(); case 'failed': return this.failedEnvironmentMessage(); - case 'creating': + case this.$options.creatingEnvironment: return this.creatingEnvironmentMessage(); default: return ''; @@ -39,17 +43,12 @@ export default { }, environmentLink() { if (this.hasEnvironment) { - return sprintf( - '%{startLink}%{name}%{endLink}', - { - startLink: `<a href="${this.deploymentStatus.environment.environment_path}" class="js-environment-link">`, - name: escape(this.deploymentStatus.environment.name), - endLink: '</a>', - }, - false, - ); + return { + link: this.deploymentStatus.environment.environment_path, + name: this.deploymentStatus.environment.name, + }; } - return ''; + return {}; }, hasLastDeployment() { return this.hasEnvironment && this.deploymentStatus.environment.last_deployment; @@ -74,201 +73,107 @@ export default { } const { name, path } = this.deploymentCluster; - const escapedName = escape(name); - const escapedPath = escape(path); - - if (!escapedPath) { - return escapedName; - } - return sprintf( - '%{startLink}%{name}%{endLink}', - { - startLink: `<a href="${escapedPath}" class="js-job-cluster-link">`, - name: escapedName, - endLink: '</a>', - }, - false, - ); + return { + path, + name, + }; }, kubernetesNamespace() { return this.hasCluster ? this.deploymentCluster.kubernetes_namespace : null; }, + deploymentLink() { + return { + path: this.lastDeploymentPath, + name: + this.deploymentStatus.status === this.$options.creatingEnvironment + ? __('latest deployment') + : __('most recent deployment'), + }; + }, }, methods: { - deploymentLink(name) { - return sprintf( - '%{startLink}%{name}%{endLink}', - { - startLink: `<a href="${this.lastDeploymentPath}" class="js-job-deployment-link">`, - name, - endLink: '</a>', - }, - false, - ); - }, failedEnvironmentMessage() { - const { environmentLink } = this; - - return sprintf( - __('The deployment of this job to %{environmentLink} did not succeed.'), - { environmentLink }, - false, - ); + return __('The deployment of this job to %{environmentLink} did not succeed.'); }, lastEnvironmentMessage() { - const { environmentLink, clusterNameOrLink, hasCluster, kubernetesNamespace } = this; - if (hasCluster) { - if (kubernetesNamespace) { - return sprintf( - __( - 'This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}.', - ), - { environmentLink, clusterNameOrLink, kubernetesNamespace }, - false, + if (this.hasCluster) { + if (this.kubernetesNamespace) { + return __( + 'This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}.', ); } // we know the cluster but not the namespace - return sprintf( - __('This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink}.'), - { environmentLink, clusterNameOrLink }, - false, - ); + return __('This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink}.'); } // not a cluster deployment - return sprintf(__('This job is deployed to %{environmentLink}.'), { environmentLink }, false); + return __('This job is deployed to %{environmentLink}.'); }, outOfDateEnvironmentMessage() { - const { - hasLastDeployment, - hasCluster, - environmentLink, - clusterNameOrLink, - kubernetesNamespace, - } = this; - - if (hasLastDeployment) { - const deploymentLink = this.deploymentLink(__('most recent deployment')); - if (hasCluster) { - if (kubernetesNamespace) { - return sprintf( - __( - 'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. View the %{deploymentLink}.', - ), - { environmentLink, clusterNameOrLink, kubernetesNamespace, deploymentLink }, - false, + if (this.hasLastDeployment) { + if (this.hasCluster) { + if (this.kubernetesNamespace) { + return __( + 'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. View the %{deploymentLink}.', ); } // we know the cluster but not the namespace - return sprintf( - __( - 'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}. View the %{deploymentLink}.', - ), - { environmentLink, clusterNameOrLink, deploymentLink }, - false, + return __( + 'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}. View the %{deploymentLink}.', ); } // not a cluster deployment - return sprintf( - __( - 'This job is an out-of-date deployment to %{environmentLink}. View the %{deploymentLink}.', - ), - { environmentLink, deploymentLink }, - false, + return __( + 'This job is an out-of-date deployment to %{environmentLink}. View the %{deploymentLink}.', ); } // no last deployment, i.e. this is the first deployment - if (hasCluster) { - if (kubernetesNamespace) { - return sprintf( - __( - 'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}.', - ), - { environmentLink, clusterNameOrLink, kubernetesNamespace }, - false, + if (this.hasCluster) { + if (this.kubernetesNamespace) { + return __( + 'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}.', ); } // we know the cluster but not the namespace - return sprintf( - __( - 'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}.', - ), - { environmentLink, clusterNameOrLink }, - false, + return __( + 'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}.', ); } // not a cluster deployment - return sprintf( - __('This job is an out-of-date deployment to %{environmentLink}.'), - { environmentLink }, - false, - ); + return __('This job is an out-of-date deployment to %{environmentLink}.'); }, creatingEnvironmentMessage() { - const { - hasLastDeployment, - hasCluster, - environmentLink, - clusterNameOrLink, - kubernetesNamespace, - } = this; - - if (hasLastDeployment) { - const deploymentLink = this.deploymentLink(__('latest deployment')); - if (hasCluster) { - if (kubernetesNamespace) { - return sprintf( - __( - 'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. This will overwrite the %{deploymentLink}.', - ), - { environmentLink, clusterNameOrLink, kubernetesNamespace, deploymentLink }, - false, + if (this.hasLastDeployment) { + if (this.hasCluster) { + if (this.kubernetesNamespace) { + return __( + 'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. This will overwrite the %{deploymentLink}.', ); } // we know the cluster but not the namespace - return sprintf( - __( - 'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}. This will overwrite the %{deploymentLink}.', - ), - { environmentLink, clusterNameOrLink, deploymentLink }, - false, + return __( + 'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}. This will overwrite the %{deploymentLink}.', ); } // not a cluster deployment - return sprintf( - __( - 'This job is creating a deployment to %{environmentLink}. This will overwrite the %{deploymentLink}.', - ), - { environmentLink, deploymentLink }, - false, + return __( + 'This job is creating a deployment to %{environmentLink}. This will overwrite the %{deploymentLink}.', ); } // no last deployment, i.e. this is the first deployment - if (hasCluster) { - if (kubernetesNamespace) { - return sprintf( - __( - 'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}.', - ), - { environmentLink, clusterNameOrLink, kubernetesNamespace }, - false, + if (this.hasCluster) { + if (this.kubernetesNamespace) { + return __( + 'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}.', ); } // we know the cluster but not the namespace - return sprintf( - __( - 'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}.', - ), - { environmentLink, clusterNameOrLink }, - false, + return __( + 'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}.', ); } // not a cluster deployment - return sprintf( - __('This job is creating a deployment to %{environmentLink}.'), - { environmentLink }, - false, - ); + return __('This job is creating a deployment to %{environmentLink}.'); }, }, }; @@ -277,7 +182,37 @@ export default { <div class="gl-mt-3 gl-mb-3 js-environment-container"> <div class="environment-information"> <ci-icon :status="iconStatus" /> - <p class="inline gl-mb-0" v-html="environment"></p> + <p class="inline gl-mb-0"> + <gl-sprintf :message="environment"> + <template #environmentLink> + <gl-link + v-if="hasEnvironment" + :href="environmentLink.link" + data-testid="job-environment-link" + v-text="environmentLink.name" + /> + </template> + <template #clusterNameOrLink> + <gl-link + v-if="clusterNameOrLink.path" + :href="clusterNameOrLink.path" + data-testid="job-cluster-link" + v-text="clusterNameOrLink.name" + /> + <template v-else>{{ clusterNameOrLink.name }}</template> + </template> + <template #kubernetesNamespace> + <template>{{ kubernetesNamespace }}</template> + </template> + <template #deploymentLink> + <gl-link + :href="deploymentLink.path" + data-testid="job-deployment-link" + v-text="deploymentLink.name" + /> + </template> + </gl-sprintf> + </p> </div> </div> </template> diff --git a/app/controllers/concerns/enforces_two_factor_authentication.rb b/app/controllers/concerns/enforces_two_factor_authentication.rb index 6c443611a60..f1dd46648f1 100644 --- a/app/controllers/concerns/enforces_two_factor_authentication.rb +++ b/app/controllers/concerns/enforces_two_factor_authentication.rb @@ -12,10 +12,17 @@ module EnforcesTwoFactorAuthentication included do before_action :check_two_factor_requirement - helper_method :two_factor_grace_period_expired?, :two_factor_skippable? + + # to include this in controllers inheriting from `ActionController::Metal` + # we need to add this block + if respond_to?(:helper_method) + helper_method :two_factor_grace_period_expired?, :two_factor_skippable? + end end def check_two_factor_requirement + return unless respond_to?(:current_user) + if two_factor_authentication_required? && current_user_requires_two_factor? redirect_to profile_two_factor_auth_path end diff --git a/app/controllers/oauth/applications_controller.rb b/app/controllers/oauth/applications_controller.rb index 6532501733a..8158db282fb 100644 --- a/app/controllers/oauth/applications_controller.rb +++ b/app/controllers/oauth/applications_controller.rb @@ -2,7 +2,6 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController include Gitlab::GonHelper - include Gitlab::Allowable include PageLayoutHelper include OauthApplications include Gitlab::Experimentation::ControllerConcern @@ -19,8 +18,6 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController around_action :set_locale - helper_method :can? - layout 'profile' def index diff --git a/app/controllers/oauth/authorizations_controller.rb b/app/controllers/oauth/authorizations_controller.rb index f6ad2bf5312..6e8686ee90b 100644 --- a/app/controllers/oauth/authorizations_controller.rb +++ b/app/controllers/oauth/authorizations_controller.rb @@ -4,7 +4,7 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController include Gitlab::Experimentation::ControllerConcern include InitializesCurrentUserMode - before_action :verify_confirmed_email!, only: [:new] + before_action :verify_confirmed_email! layout 'profile' diff --git a/app/controllers/oauth/authorized_applications_controller.rb b/app/controllers/oauth/authorized_applications_controller.rb index addec71f0bf..3f476c0d717 100644 --- a/app/controllers/oauth/authorized_applications_controller.rb +++ b/app/controllers/oauth/authorized_applications_controller.rb @@ -16,7 +16,7 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio if params[:token_id].present? current_resource_owner.oauth_authorized_tokens.find(params[:token_id]).revoke else - Doorkeeper::AccessToken.revoke_all_for(params[:id], current_resource_owner) + Doorkeeper::Application.revoke_tokens_and_grants_for(params[:id], current_resource_owner) end redirect_to applications_profile_url, diff --git a/app/controllers/oauth/token_info_controller.rb b/app/controllers/oauth/token_info_controller.rb index 492c24b53b1..e37f8992d92 100644 --- a/app/controllers/oauth/token_info_controller.rb +++ b/app/controllers/oauth/token_info_controller.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class Oauth::TokenInfoController < Doorkeeper::TokenInfoController + include EnforcesTwoFactorAuthentication + def show if doorkeeper_token && doorkeeper_token.accessible? token_json = doorkeeper_token.as_json diff --git a/app/controllers/oauth/tokens_controller.rb b/app/controllers/oauth/tokens_controller.rb new file mode 100644 index 00000000000..012fa318eea --- /dev/null +++ b/app/controllers/oauth/tokens_controller.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class Oauth::TokensController < Doorkeeper::TokensController + include EnforcesTwoFactorAuthentication +end diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index dccb89eec79..c9ba42491f3 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -29,7 +29,7 @@ module IssuablesHelper def sidebar_milestone_tooltip_label(milestone) return _('Milestone') unless milestone.present? - [milestone[:title], sidebar_milestone_remaining_days(milestone) || _('Milestone')].join('<br/>') + [escape_once(milestone[:title]), sidebar_milestone_remaining_days(milestone) || _('Milestone')].join('<br/>') end def sidebar_milestone_remaining_days(milestone) diff --git a/app/mailers/emails/members.rb b/app/mailers/emails/members.rb index 06d2219d6a9..07ce9bba784 100644 --- a/app/mailers/emails/members.rb +++ b/app/mailers/emails/members.rb @@ -13,6 +13,8 @@ module Emails @member_source_type = member_source_type @member_id = member_id + return unless member_exists? + user = User.find(recipient_id) member_email_with_layout( @@ -24,6 +26,8 @@ module Emails @member_source_type = member_source_type @member_id = member_id + return unless member_exists? + member_email_with_layout( to: member.user.notification_email_for(notification_group), subject: subject("Access to the #{member_source.human_name} #{member_source.model_name.singular} was granted")) @@ -45,6 +49,8 @@ module Emails @member_id = member_id @token = token + return unless member_exists? + member_email_with_layout( to: member.invite_email, subject: subject("Invitation to join the #{member_source.human_name} #{member_source.model_name.singular}")) @@ -53,6 +59,8 @@ module Emails def member_invite_accepted_email(member_source_type, member_id) @member_source_type = member_source_type @member_id = member_id + + return unless member_exists? return unless member.created_by member_email_with_layout( @@ -74,9 +82,11 @@ module Emails subject: subject('Invitation declined')) end + # rubocop: disable CodeReuse/ActiveRecord def member - @member ||= Member.find(@member_id) + @member ||= Member.find_by(id: @member_id) end + # rubocop: enable CodeReuse/ActiveRecord def member_source @member_source ||= member.source @@ -88,6 +98,11 @@ module Emails private + def member_exists? + Gitlab::AppLogger.info("Tried to send an email invitation for a deleted group. Member id: #{@member_id}") if member.blank? + member.present? + end + def member_source_class @member_source_type.classify.constantize end diff --git a/app/models/clusters/applications/runner.rb b/app/models/clusters/applications/runner.rb index 9ec7c194a26..3f0b4edde35 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.18.1' + VERSION = '0.18.2' self.table_name = 'clusters_applications_runners' diff --git a/app/services/authorized_project_update/project_group_link_create_service.rb b/app/services/authorized_project_update/project_group_link_create_service.rb index db2db091374..090b22a7820 100644 --- a/app/services/authorized_project_update/project_group_link_create_service.rb +++ b/app/services/authorized_project_update/project_group_link_create_service.rb @@ -6,9 +6,10 @@ module AuthorizedProjectUpdate BATCH_SIZE = 1000 - def initialize(project, group) + def initialize(project, group, group_access = nil) @project = project @group = group + @group_access = group_access end def execute @@ -19,19 +20,20 @@ module AuthorizedProjectUpdate user_ids_to_delete = [] members.each do |member| + new_access_level = access_level(member.access_level) existing_access_level = existing_authorizations[member.user_id] if existing_access_level # User might already have access to the project unrelated to the # current project share - next if existing_access_level >= member.access_level + next if existing_access_level >= new_access_level user_ids_to_delete << member.user_id end authorizations_to_create << { user_id: member.user_id, project_id: project.id, - access_level: member.access_level } + access_level: new_access_level } end update_authorizations(user_ids_to_delete, authorizations_to_create) @@ -42,7 +44,15 @@ module AuthorizedProjectUpdate private - attr_reader :project, :group + attr_reader :project, :group, :group_access + + def access_level(membership_access_level) + return membership_access_level unless group_access + + # access level must not be higher than the max access level set when + # creating the project share + [membership_access_level, group_access].min + end def existing_project_authorizations(members) user_ids = members.map(&:user_id) diff --git a/app/services/groups/transfer_service.rb b/app/services/groups/transfer_service.rb index fbbf4ce8baf..f2fb494500d 100644 --- a/app/services/groups/transfer_service.rb +++ b/app/services/groups/transfer_service.rb @@ -37,6 +37,7 @@ module Groups # Overridden in EE def post_update_hooks(updated_project_ids) + refresh_project_authorizations end def ensure_allowed_transfer @@ -121,6 +122,16 @@ module Groups @group.add_owner(current_user) end + def refresh_project_authorizations + ProjectAuthorization.where(project_id: @group.all_projects.select(:id)).delete_all # rubocop: disable CodeReuse/ActiveRecord + + # refresh authorized projects for current_user immediately + current_user.refresh_authorized_projects + + # schedule refreshing projects for all the members of the group + @group.refresh_members_authorized_projects + end + def raise_transfer_error(message) raise TransferError, localized_error_messages[message] end diff --git a/app/services/projects/group_links/create_service.rb b/app/services/projects/group_links/create_service.rb index 3c3cab26fb5..3fcc721fe65 100644 --- a/app/services/projects/group_links/create_service.rb +++ b/app/services/projects/group_links/create_service.rb @@ -13,7 +13,7 @@ module Projects ) if link.save - setup_authorizations(group) + setup_authorizations(group, link.group_access) success(link: link) else error(link.errors.full_messages.to_sentence, 409) @@ -22,9 +22,10 @@ module Projects private - def setup_authorizations(group) + def setup_authorizations(group, group_access = nil) if Feature.enabled?(:specialized_project_authorization_project_share_worker) - AuthorizedProjectUpdate::ProjectGroupLinkCreateWorker.perform_async(project.id, group.id) + AuthorizedProjectUpdate::ProjectGroupLinkCreateWorker.perform_async( + project.id, group.id, group_access) # AuthorizedProjectsWorker uses an exclusive lease per user but # specialized workers might have synchronization issues. Until we diff --git a/app/workers/authorized_project_update/project_group_link_create_worker.rb b/app/workers/authorized_project_update/project_group_link_create_worker.rb index 5fb59efaacb..dd24a9602bb 100644 --- a/app/workers/authorized_project_update/project_group_link_create_worker.rb +++ b/app/workers/authorized_project_update/project_group_link_create_worker.rb @@ -10,12 +10,13 @@ module AuthorizedProjectUpdate idempotent! - def perform(project_id, group_id) + def perform(project_id, group_id, group_access = nil) project = Project.find(project_id) group = Group.find(group_id) - AuthorizedProjectUpdate::ProjectGroupLinkCreateService.new(project, group) - .execute + AuthorizedProjectUpdate::ProjectGroupLinkCreateService + .new(project, group, group_access) + .execute end end end diff --git a/app/workers/authorized_projects_worker.rb b/app/workers/authorized_projects_worker.rb index 62eea8e0462..f5132459131 100644 --- a/app/workers/authorized_projects_worker.rb +++ b/app/workers/authorized_projects_worker.rb @@ -16,6 +16,9 @@ class AuthorizedProjectsWorker if Rails.env.test? def self.bulk_perform_and_wait(args_list, timeout: 10) end + + def self.bulk_perform_inline(args_list) + end end # rubocop: disable CodeReuse/ActiveRecord |