Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-11-05 18:12:21 +00:00
parent 81a37f0581
commit 25307dda30
44 changed files with 778 additions and 206 deletions

View File

@ -1,3 +1,7 @@
<!-- This template is used as a starting point for understing and articulating a customer problem.
Learn more about it in the handbook: https://about.gitlab.com/handbook/product-development-flow/#validation-phase-2-problem-validation
-->
## Problem Statement
<!-- What is the problem we hope to validate? Reference how to write a real customer problem statement at https://productcoalition.com/how-to-write-a-good-customer-problem-statement-a815f80189ba for guidance. -->
@ -45,4 +49,8 @@ For example, if the solution will take a product manager, designer, and engineer
- [ ] The problem is well described and detailed with necessary requirements for product design to understand the problem
- [ ] The problem is well described and detailed with necessary requirements for engineering to understand the problem
## Research Issue
<!-- Link to the Problem Validation Research issue that will be executed by the UX Researcher. https://gitlab.com/gitlab-org/ux-research/ -->
/label ~"workflow::validation backlog" ~devops:: ~category: ~group::

View File

@ -2293,6 +2293,15 @@ entry.
- [Remove diffs gradual load feature flag](gitlab-org/gitlab@027d7c4327b5b6205a84281239027273517bf81b) ([merge request](gitlab-org/gitlab!55478))
- [Remove partial index for Hashed Storage migration](gitlab-org/gitlab@3ed017a1023d7b0941a7606b69e6caee8d22f15c) ([merge request](gitlab-org/gitlab!62920))
## 14.0.12 (2021-11-05)
### Changed (4 changes)
- [Geo: Alternate redownload and normal design sync attempts](gitlab-org/gitlab@ed34172e5c7425316480efb732a9429e93e81017) ([merge request](gitlab-org/gitlab!73722)) **GitLab Enterprise Edition**
- [Geo: Alternate redownload and normal SSF sync attempts](gitlab-org/gitlab@c0f2f40b98c4b9fc72c21c474a2224e045263ea2) ([merge request](gitlab-org/gitlab!73722)) **GitLab Enterprise Edition**
- [Geo: Alternate redownload and normal project syncs](gitlab-org/gitlab@6370a7258719d5eb0ad83c54383ecb7f4fd54fc2) ([merge request](gitlab-org/gitlab!73722)) **GitLab Enterprise Edition**
- [Geo: Reduce frequency of redownload attempts](gitlab-org/gitlab@1bcd41f28733b01286a42689857f6530c0805186) ([merge request](gitlab-org/gitlab!73722)) **GitLab Enterprise Edition**
## 14.0.11 (2021-09-23)
### Fixed (1 change)

View File

@ -128,6 +128,7 @@ export default {
</p>
<gl-tabs>
<slot name="ee-security-tab"></slot>
<gl-tab>
<template #title>
<span data-testid="cluster-agent-token-count">

View File

@ -1,7 +1,7 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import AgentShowPage from './components/show.vue';
import AgentShowPage from 'ee_else_ce/clusters/agents/components/show.vue';
Vue.use(VueApollo);

View File

@ -0,0 +1,50 @@
<script>
import { GlTab, GlTabs } from '@gitlab/ui';
import IncubationBanner from './incubation_banner.vue';
import ServiceAccounts from './service_accounts.vue';
export default {
components: { GlTab, GlTabs, IncubationBanner, ServiceAccounts },
props: {
serviceAccounts: {
type: Array,
required: true,
},
createServiceAccountUrl: {
type: String,
required: true,
},
emptyIllustrationUrl: {
type: String,
required: true,
},
},
methods: {
feedbackUrl(template) {
return `https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/meta/-/issues/new?issuable_template=${template}`;
},
},
};
</script>
<template>
<div>
<incubation-banner
:share-feedback-url="feedbackUrl('general_feedback')"
:report-bug-url="feedbackUrl('report_bug')"
:feature-request-url="feedbackUrl('feature_request')"
/>
<gl-tabs>
<gl-tab :title="__('Configuration')">
<service-accounts
class="gl-mx-3"
:list="serviceAccounts"
:create-url="createServiceAccountUrl"
:empty-illustration-url="emptyIllustrationUrl"
/>
</gl-tab>
<gl-tab :title="__('Deployments')" disabled />
<gl-tab :title="__('Services')" disabled />
</gl-tabs>
</div>
</template>

View File

@ -0,0 +1,44 @@
<script>
import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
export default {
components: { GlAlert, GlLink, GlSprintf },
props: {
shareFeedbackUrl: {
required: true,
type: String,
},
reportBugUrl: {
required: true,
type: String,
},
featureRequestUrl: {
required: true,
type: String,
},
},
};
</script>
<template>
<gl-alert :dismissible="false" variant="info">
{{ __('This is an experimental feature developed by GitLab Incubation Engineering.') }}
<gl-sprintf
:message="
__(
'We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}',
)
"
>
<template #featureLink="{ content }">
<gl-link :href="featureRequestUrl">{{ content }}</gl-link>
</template>
<template #bugLink="{ content }">
<gl-link :href="reportBugUrl">{{ content }}</gl-link>
</template>
<template #feedbackLink="{ content }">
<gl-link :href="shareFeedbackUrl">{{ content }}</gl-link>
</template>
</gl-sprintf>
</gl-alert>
</template>

View File

@ -0,0 +1,65 @@
<script>
import { GlButton, GlEmptyState, GlTable } from '@gitlab/ui';
import { __ } from '~/locale';
export default {
components: { GlButton, GlEmptyState, GlTable },
props: {
list: {
type: Array,
required: true,
},
createUrl: {
type: String,
required: true,
},
emptyIllustrationUrl: {
type: String,
required: true,
},
},
data() {
return {
tableFields: [
{ key: 'environment', label: __('Environment'), sortable: true },
{ key: 'gcp_project', label: __('Google Cloud Project'), sortable: true },
{ key: 'service_account_exists', label: __('Service Account'), sortable: true },
{ key: 'service_account_key_exists', label: __('Service Account Key'), sortable: true },
],
};
},
};
</script>
<template>
<div>
<gl-empty-state
v-if="list.length === 0"
:title="__('No service accounts')"
:description="
__('Service Accounts keys authorize GitLab to deploy your Google Cloud project')
"
:primary-button-link="createUrl"
:primary-button-text="__('Create service account')"
:svg-path="emptyIllustrationUrl"
/>
<div v-else>
<h2 class="gl-font-size-h2">{{ __('Service Accounts') }}</h2>
<p>{{ __('Service Accounts keys authorize GitLab to deploy your Google Cloud project') }}</p>
<gl-table :items="list" :fields="tableFields">
<template #cell(service_account_exists)="{ value }">
{{ value ? '✔' : __('Not found') }}
</template>
<template #cell(service_account_key_exists)="{ value }">
{{ value ? '✔' : __('Not found') }}
</template>
</gl-table>
<gl-button :href="createUrl" category="primary" variant="info">
{{ __('Create service account') }}
</gl-button>
</div>
</div>
</template>

View File

@ -0,0 +1,19 @@
import Vue from 'vue';
import App from './components/app.vue';
const elementRenderer = (element, props = {}) => (createElement) =>
createElement(element, { props });
export default () => {
const root = document.querySelector('#js-google-cloud');
// uncomment this once backend is ready
// const dataset = JSON.parse(root.getAttribute('data'));
const mockDataset = {
createServiceAccountUrl: '#create-url',
serviceAccounts: [],
emptyIllustrationUrl:
'https://gitlab.com/gitlab-org/gitlab-svgs/-/raw/main/illustrations/pipelines_empty.svg',
};
return new Vue({ el: root, render: elementRenderer(App, mockDataset) });
};

View File

@ -0,0 +1,3 @@
import initGoogleCloud from '~/google_cloud/index';
initGoogleCloud();

View File

@ -23,14 +23,14 @@ export default class Project {
});
}
$('.hide-no-ssh-message').on('click', function (e) {
$('.js-hide-no-ssh-message').on('click', function (e) {
Cookies.set('hide_no_ssh_message', 'false');
$(this).parents('.no-ssh-key-message').remove();
$(this).parents('.js-no-ssh-key-message').remove();
return e.preventDefault();
});
$('.hide-no-password-message').on('click', function (e) {
$('.js-hide-no-password-message').on('click', function (e) {
Cookies.set('hide_no_password_message', 'false');
$(this).parents('.no-password-message').remove();
$(this).parents('.js-no-password-message').remove();
return e.preventDefault();
});
$('.hide-auto-devops-implicitly-enabled-banner').on('click', function (e) {

View File

@ -1,5 +1,5 @@
<script>
import { GlModal, GlModalDirective, GlFormTextarea, GlButton } from '@gitlab/ui';
import { GlModal, GlModalDirective, GlFormInput, GlButton } from '@gitlab/ui';
import { uniqueId } from 'lodash';
import csrf from '~/lib/utils/csrf';
import { __ } from '~/locale';
@ -7,7 +7,7 @@ import { __ } from '~/locale';
export default {
components: {
GlModal,
GlFormTextarea,
GlFormInput,
GlButton,
},
directives: {
@ -88,7 +88,12 @@ export default {
<p>
<code class="gl-white-space-pre-wrap">{{ confirmPhrase }}</code>
</p>
<gl-form-textarea id="confirm_name_input" v-model="userInput" name="confirm_name_input" />
<gl-form-input
id="confirm_name_input"
v-model="userInput"
name="confirm_name_input"
type="text"
/>
<slot name="modal-footer"></slot>
</div>
</gl-modal>

View File

@ -1,7 +1,7 @@
import Vue from 'vue';
import TermsApp from 'jh_else_ce/terms/components/app.vue';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import TermsApp from './components/app.vue';
export const initTermsApp = () => {
const el = document.getElementById('js-terms-of-service');

View File

@ -3,6 +3,10 @@
class Projects::ClusterAgentsController < Projects::ApplicationController
before_action :authorize_can_read_cluster_agent!
before_action do
push_frontend_feature_flag(:cluster_vulnerabilities, project, default_enabled: :yaml)
end
feature_category :kubernetes_management
def show
@ -17,3 +21,5 @@ class Projects::ClusterAgentsController < Projects::ApplicationController
access_denied!
end
end
Projects::ClusterAgentsController.prepend_mod_with('Projects::ClusterAgentsController')

View File

@ -196,12 +196,26 @@ module ProjectsHelper
cookies["hide_auto_devops_implicitly_enabled_banner_#{project.id}".to_sym].blank?
end
def link_to_set_password
if current_user.require_password_creation_for_git?
link_to s_('SetPasswordToCloneLink|set a password'), edit_profile_password_path
else
link_to s_('CreateTokenToCloneLink|create a personal access token'), profile_personal_access_tokens_path
end
def no_password_message
push_pull_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('gitlab-basics/start-using-git', anchor: 'pull-and-push') }
clone_with_https_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('gitlab-basics/start-using-git', anchor: 'clone-with-https') }
set_password_link_start = '<a href="%{url}">'.html_safe % { url: edit_profile_password_path }
set_up_pat_link_start = '<a href="%{url}">'.html_safe % { url: profile_personal_access_tokens_path }
message = if current_user.require_password_creation_for_git?
_('Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}.')
else
_('Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}.')
end
html_escape(message) % {
push_pull_link_start: push_pull_link_start,
protocol: gitlab_config.protocol.upcase,
clone_with_https_link_start: clone_with_https_link_start,
set_password_link_start: set_password_link_start,
set_up_pat_link_start: set_up_pat_link_start,
link_end: '</a>'.html_safe
}
end
# Returns true if any projects are present.
@ -384,12 +398,11 @@ module ProjectsHelper
# Returns the confirm phrase the user needs to type in order to delete the project
#
# Occasionally a user will delete one project, believing it is a different (similar) one.
# Specifically, a user might delete an original project, believing it is a fork.
# Thus the phrase should be the project full name to include the namespace.
# Thus the phrase should include the namespace to make it very clear to the
# user which project is subject to deletion.
# Relevant issue: https://gitlab.com/gitlab-org/gitlab/-/issues/343591
def delete_confirm_phrase(project)
s_('DeleteProject|Delete %{name}') % { name: project.full_name }
project.path_with_namespace
end
private

View File

@ -48,7 +48,7 @@ class CommitStatus < Ci::ApplicationRecord
scope :ordered, -> { order(:name) }
scope :ordered_by_stage, -> { order(stage_idx: :asc) }
scope :latest_ordered, -> { latest.ordered.includes(project: :namespace) }
scope :retried_ordered, -> { retried.ordered.includes(project: :namespace) }
scope :retried_ordered, -> { retried.order(name: :asc, id: :desc).includes(project: :namespace) }
scope :ordered_by_pipeline, -> { order(pipeline_id: :asc) }
scope :before_stage, -> (index) { where('stage_idx < ?', index) }
scope :for_stage, -> (index) { where(stage_idx: index) }

View File

@ -7,6 +7,7 @@ class MergeRequestDiffCommit < ApplicationRecord
include ShaAttribute
include CachedCommit
include IgnorableColumns
include FromUnion
ignore_column %i[author_name author_email committer_name committer_email],
remove_with: '14.6',

View File

@ -473,7 +473,11 @@ class User < ApplicationRecord
end
def active_for_authentication?
super && can?(:log_in)
return false unless super
check_ldap_if_ldap_blocked!
can?(:log_in)
end
# The messages for these keys are defined in `devise.en.yml`
@ -2167,6 +2171,13 @@ class User < ApplicationRecord
def ci_job_token_scope_cache_key
"users:#{id}:ci:job_token_scope"
end
# An `ldap_blocked` user will be unblocked if LDAP indicates they are allowed.
def check_ldap_if_ldap_blocked!
return unless ::Gitlab::Auth::Ldap::Config.enabled? && ldap_blocked?
::Gitlab::Auth::Ldap::Access.allowed?(self)
end
end
User.prepend_mod_with('User')

View File

@ -1,12 +1,10 @@
- if show_no_password_message?
.no-password-message.gl-alert.gl-alert-warning
= sprite_icon('warning', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
%button.js-close.gl-alert-dismiss{ type: 'button', 'aria-label': _('Dismiss') }
= sprite_icon('close', size: 16, css_class: 'gl-icon')
= render 'shared/global_alert',
variant: :warning,
alert_class: 'js-no-password-message',
close_button_class: 'js-hide-no-password-message' do
.gl-alert-body
- translation_params = { protocol: gitlab_config.protocol.upcase, set_password_link: link_to_set_password }
- set_password_message = _("You won't be able to pull or push repositories via %{protocol} until you %{set_password_link} on your account") % translation_params
= set_password_message.html_safe
= no_password_message
.gl-alert-actions
= link_to _('Remind later'), '#', class: 'hide-no-password-message btn gl-alert-action btn-info btn-md gl-button'
= link_to _("Don't show again"), profile_path(user: {hide_no_password: true}), method: :put, role: 'button', class: 'btn gl-alert-action btn-md btn-default gl-button btn-default-secondary'
= link_to _('Remind later'), '#', class: 'js-hide-no-password-message gl-alert-action btn btn-confirm btn-md gl-button'
= link_to _("Don't show again"), profile_path(user: { hide_no_password: true }), method: :put, role: 'button', class: 'gl-alert-action btn btn-default btn-md gl-button'

View File

@ -1,10 +1,10 @@
- if show_no_ssh_key_message?
%div{ class: 'no-ssh-key-message gl-alert gl-alert-warning', role: 'alert' }
= sprite_icon('warning', css_class: 'gl-icon s16 gl-alert-icon gl-alert-icon-no-title')
%button{ class: 'gl-alert-dismiss hide-no-ssh-message', type: 'button', 'aria-label': _('Dismiss') }
= sprite_icon('close', css_class: 'gl-icon s16')
= render 'shared/global_alert',
variant: :warning,
alert_class: 'js-no-ssh-message',
close_button_class: 'js-hide-no-ssh-message' do
.gl-alert-body
= s_("MissingSSHKeyWarningLink|You won't be able to pull or push repositories via SSH until you add an SSH key to your profile")
= s_("MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile.")
.gl-alert-actions
= link_to s_('MissingSSHKeyWarningLink|Add SSH key'), profile_keys_path, class: "btn gl-alert-action btn-warning btn-md gl-button"
= link_to s_("MissingSSHKeyWarningLink|Don't show again"), profile_path(user: {hide_no_ssh_key: true}), method: :put, role: 'button', class: 'btn gl-alert-action btn-md btn-warning gl-button btn-warning-secondary'
= link_to s_('MissingSSHKeyWarningLink|Add SSH key'), profile_keys_path, class: "gl-alert-action btn btn-confirm btn-md gl-button"
= link_to s_("MissingSSHKeyWarningLink|Don't show again"), profile_path(user: { hide_no_ssh_key: true }), method: :put, role: 'button', class: 'gl-alert-action btn btn-default btn-md gl-button'

View File

@ -0,0 +1,8 @@
---
name: cluster_vulnerabilities
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73321
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343917
milestone: '14.5'
type: development
group: group::container security
default_enabled: false

View File

@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343046
milestone: '14.5'
type: development
group: group::access
default_enabled: false
default_enabled: true

View File

@ -42,11 +42,15 @@ GitLab to an earlier version, the feature flag status may change.
Features that are disabled by default may change or be removed without notice in a future version of GitLab.
Data corruption, stability degradation, or performance degradation might occur if
Data corruption, stability degradation, performance degradation, or security issues might occur if
you enable a feature that's disabled by default. Problems caused by using a default
disabled feature aren't covered by GitLab support, unless you were directed by GitLab
to enable the feature.
Security issues found in features that are disabled by default are patched in regular releases
and do not follow our regular [maintenance policy](../policy/maintenance.md#security-releases)
with regards to backporting the fix.
## Risks when disabling released features
In most cases, the feature flag code is removed in a future version of GitLab.

View File

@ -74,6 +74,20 @@ you want using steps 1 and 2 from the GitLab downloads page.
postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.10.1.30/32 10.10.1.31/32 10.10.1.32/32 10.10.1.33/32 10.10.1.38/32)
```
1. If you run multiple Sidekiq nodes with a shared file storage, such as NFS, you must
specify the UIDs and GIDs to ensure they match between servers. Specifying the UIDs
and GIDs prevents permissions issues in the file system. This advice is similar to the
[advice for Geo setups](geo/replication/multiple_servers.md#step-4-configure-the-frontend-application-nodes-on-the-geo-secondary-site):
```ruby
user['uid'] = 9000
user['gid'] = 9000
web_server['uid'] = 9001
web_server['gid'] = 9001
registry['uid'] = 9002
registry['gid'] = 9002
```
1. Disable other services:
```ruby

View File

@ -56,11 +56,18 @@ To add this badge to a project:
## Group badges
Badges can be added to a group and are visible on every project's
overview page that's under that group. In this case, they cannot be edited or
deleted on the project level. If you need to have individual badges for each
project, consider adding them on the [project level](#project-badges) or use
[placeholders](#placeholders).
By adding a badge to a group, you add and enforce a project-level badge
for all projects in the group. The group badge is visible on the **Overview**
page of any project that belongs to the group.
NOTE:
While these badges appear as project-level badges in the codebase, they
cannot be edited or deleted at the project level.
If you need individual badges for each project, either:
- Add the badge at the [project level](#project-badges).
- Use [placeholders](#placeholders).
To add a new badge to a group:

View File

@ -44,7 +44,22 @@ Users with the [Owner role](../../permissions.md) in a group can
[import and export group wikis](../../group/settings/import_export.md) when importing
or exporting a group.
Content created in a group wiki is not deleted when an account is downgraded or a GitLab trial ends.
Content created in a group wiki is not deleted when an account is downgraded or a
GitLab trial ends. The group wiki data is exported whenever the group owner of
the wiki is exported.
To access the group wiki data from the export file if the feature is no longer
available, you have to:
1. Extract the [export file tarball](../../group/settings/import_export.md) with
this command, replacing `FILENAME` with your file's name:
`tar -xvzf FILENAME.tar.gz`
1. Browse to the `repositories` directory. This directory contains a
[Git bundle](https://git-scm.com/docs/git-bundle) with the extension `.wiki.bundle`.
1. Clone the Git bundle into a new repository, replacing `FILENAME` with
your bundle's name: `git clone FILENAME.wiki.bundle`
All files in the wiki are available in this Git repository.
## Related topics

View File

@ -1,56 +0,0 @@
# frozen_string_literal: true
module BulkImports
module Groups
module Graphql
module GetMilestonesQuery
extend self
def to_s
<<-'GRAPHQL'
query ($full_path: ID!, $cursor: String, $per_page: Int) {
group(fullPath: $full_path) {
milestones(first: $per_page, after: $cursor, includeDescendants: false) {
page_info: pageInfo {
next_page: endCursor
has_next_page: hasNextPage
}
nodes {
iid
title
description
state
start_date: startDate
due_date: dueDate
created_at: createdAt
updated_at: updatedAt
}
}
}
}
GRAPHQL
end
def variables(context)
{
full_path: context.entity.source_full_path,
cursor: context.tracker.next_page,
per_page: ::BulkImports::Tracker::DEFAULT_PAGE_SIZE
}
end
def base_path
%w[data group milestones]
end
def data_path
base_path << 'nodes'
end
def page_info_path
base_path << 'page_info'
end
end
end
end
end

View File

@ -10,7 +10,10 @@ module Gitlab
# this process needs Git/Gitaly access, and duplicating all that code is far
# too much, this migration relies on global models such as Project,
# MergeRequest, etc.
# rubocop: disable Metrics/ClassLength
class FixMergeRequestDiffCommitUsers
BATCH_SIZE = 100
def initialize
@commits = {}
@users = {}
@ -33,24 +36,47 @@ module Gitlab
# Loading everything using one big query may result in timeouts (e.g.
# for projects the size of gitlab-org/gitlab). So instead we query
# data on a per merge request basis.
project.merge_requests.each_batch do |mrs|
::MergeRequestDiffCommit
.select([
:merge_request_diff_id,
:relative_order,
:sha,
:committer_id,
:commit_author_id
])
.joins(merge_request_diff: :merge_request)
.where(merge_requests: { id: mrs.select(:id) })
.where('commit_author_id IS NULL OR committer_id IS NULL')
.each do |commit|
project.merge_requests.each_batch(column: :iid) do |mrs|
mrs.ids.each do |mr_id|
each_row_to_check(mr_id) do |commit|
update_commit(project, commit)
end
end
end
end
def each_row_to_check(merge_request_id, &block)
columns = %w[merge_request_diff_id relative_order].map do |col|
Pagination::Keyset::ColumnOrderDefinition.new(
attribute_name: col,
order_expression: MergeRequestDiffCommit.arel_table[col.to_sym].asc,
nullable: :not_nullable,
distinct: false
)
end
order = Pagination::Keyset::Order.build(columns)
scope = MergeRequestDiffCommit
.joins(:merge_request_diff)
.where(merge_request_diffs: { merge_request_id: merge_request_id })
.where('commit_author_id IS NULL OR committer_id IS NULL')
.order(order)
Pagination::Keyset::Iterator
.new(scope: scope, use_union_optimization: true)
.each_batch(of: BATCH_SIZE) do |rows|
rows
.select([
:merge_request_diff_id,
:relative_order,
:sha,
:committer_id,
:commit_author_id
])
.each(&block)
end
end
# rubocop: disable Metrics/AbcSize
def update_commit(project, row)
commit = find_commit(project, row.sha)
@ -125,5 +151,6 @@ module Gitlab
MergeRequestDiffCommit.arel_table
end
end
# rubocop: enable Metrics/ClassLength
end
end

View File

@ -2914,6 +2914,9 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
msgid "AdvancedSearch|Reindex required"
msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@ -7400,6 +7403,9 @@ msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
msgid "ClusterAgents|Security"
msgstr ""
msgid "ClusterAgents|Select an Agent"
msgstr ""
@ -9742,6 +9748,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
msgid "Create service account"
msgstr ""
msgid "Create snippet"
msgstr ""
@ -9775,9 +9784,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@ -11107,9 +11113,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
msgid "DeleteProject|Delete %{name}"
msgstr ""
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@ -16034,6 +16037,9 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
msgid "Google Cloud Project"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
msgstr ""
@ -18647,6 +18653,9 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
msgstr ""
msgid "Introducing Your DevOps Reports"
msgstr ""
@ -22387,6 +22396,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
msgstr ""
msgid "MissingSSHKeyWarningLink|You won't be able to pull or push repositories via SSH until you add an SSH key to your profile"
msgstr ""
@ -23366,6 +23378,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
msgid "No service accounts"
msgstr ""
msgid "No severity matches the provided parameter"
msgstr ""
@ -23461,6 +23476,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
msgid "Not found"
msgstr ""
msgid "Not found."
msgstr ""
@ -31282,6 +31300,18 @@ msgstr ""
msgid "Service"
msgstr ""
msgid "Service Account"
msgstr ""
msgid "Service Account Key"
msgstr ""
msgid "Service Accounts"
msgstr ""
msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
msgstr ""
@ -31336,6 +31366,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
msgid "Services"
msgstr ""
msgid "Session ID"
msgstr ""
@ -31474,9 +31507,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
msgid "SetStatusModal|Add status emoji"
msgstr ""
@ -35110,6 +35140,9 @@ msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
msgid "This is an experimental feature developed by GitLab Incubation Engineering."
msgstr ""
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@ -37021,6 +37054,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
msgid "UsageQuota|No CI minutes usage data available."
msgstr ""
msgid "UsageQuota|Packages"
msgstr ""
@ -38356,6 +38392,9 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
msgstr ""
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@ -39552,9 +39591,6 @@ msgstr ""
msgid "You won't be able to create new projects because you have reached your project limit."
msgstr ""
msgid "You won't be able to pull or push repositories via %{protocol} until you %{set_password_link} on your account"
msgstr ""
msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
@ -39705,6 +39741,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
msgstr ""
msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
msgstr ""
msgid "Your account is locked."
msgstr ""

View File

@ -55,9 +55,9 @@
"@babel/preset-env": "^7.10.1",
"@gitlab/at.js": "1.5.7",
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/svgs": "1.219.0",
"@gitlab/svgs": "1.220.0",
"@gitlab/tributejs": "1.0.0",
"@gitlab/ui": "32.31.0",
"@gitlab/ui": "32.33.0",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "6.1.4-1",
"@rails/ujs": "6.1.4-1",

View File

@ -3,6 +3,9 @@
require 'spec_helper'
RSpec.describe 'No Password Alert' do
let_it_be(:message_password_auth_enabled) { 'Your account is authenticated with SSO or SAML. To push and pull over HTTP with Git using this account, you must set a password or set up a Personal Access Token to use instead of a password. For more information, see Clone with HTTPS.' }
let_it_be(:message_password_auth_disabled) { 'Your account is authenticated with SSO or SAML. To push and pull over HTTP with Git using this account, you must set up a Personal Access Token to use instead of a password. For more information, see Clone with HTTPS.' }
let(:project) { create(:project, :repository, namespace: user.namespace) }
context 'with internal auth enabled' do
@ -15,7 +18,7 @@ RSpec.describe 'No Password Alert' do
let(:user) { create(:user) }
it 'shows no alert' do
expect(page).not_to have_content "You won't be able to pull or push repositories via HTTP until you set a password on your account"
expect(page).not_to have_content message_password_auth_enabled
end
end
@ -23,7 +26,7 @@ RSpec.describe 'No Password Alert' do
let(:user) { create(:user, password_automatically_set: true) }
it 'shows a password alert' do
expect(page).to have_content "You won't be able to pull or push repositories via HTTP until you set a password on your account"
expect(page).to have_content message_password_auth_enabled
end
end
end
@ -41,7 +44,7 @@ RSpec.describe 'No Password Alert' do
gitlab_sign_in_via('saml', user, 'my-uid')
visit project_path(project)
expect(page).to have_content "You won't be able to pull or push repositories via HTTP until you create a personal access token on your account"
expect(page).to have_content message_password_auth_disabled
end
end
@ -51,7 +54,7 @@ RSpec.describe 'No Password Alert' do
gitlab_sign_in_via('saml', user, 'my-uid')
visit project_path(project)
expect(page).not_to have_content "You won't be able to pull or push repositories via HTTP until you create a personal access token on your account"
expect(page).not_to have_content message_password_auth_disabled
end
end
end

View File

@ -257,7 +257,7 @@ RSpec.describe 'Project' do
end
it 'deletes a project', :sidekiq_inline do
expect { remove_with_confirm('Delete project', "Delete #{project.full_name}", 'Yes, delete project') }.to change { Project.count }.by(-1)
expect { remove_with_confirm('Delete project', project.path_with_namespace, 'Yes, delete project') }.to change { Project.count }.by(-1)
expect(page).to have_content "Project '#{project.full_name}' is in the process of being deleted."
expect(Project.all.count).to be_zero
expect(project.issues).to be_empty

View File

@ -1,6 +1,8 @@
import { GlAlert, GlKeysetPagination, GlLoadingIcon, GlSprintf, GlTab } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import ClusterAgentShow from '~/clusters/agents/components/show.vue';
import TokenTable from '~/clusters/agents/components/token_table.vue';
import getAgentQuery from '~/clusters/agents/graphql/queries/get_cluster_agent.query.graphql';
@ -40,28 +42,34 @@ describe('ClusterAgentShow', () => {
queryResponse || jest.fn().mockResolvedValue({ data: { project: { clusterAgent } } });
const apolloProvider = createMockApollo([[getAgentQuery, agentQueryResponse]]);
wrapper = shallowMount(ClusterAgentShow, {
localVue,
apolloProvider,
propsData,
stubs: { GlSprintf, TimeAgoTooltip, GlTab },
});
wrapper = extendedWrapper(
shallowMount(ClusterAgentShow, {
localVue,
apolloProvider,
propsData,
stubs: { GlSprintf, TimeAgoTooltip, GlTab },
}),
);
};
const createWrapperWithoutApollo = ({ clusterAgent, loading = false }) => {
const createWrapperWithoutApollo = ({ clusterAgent, loading = false, slots = {} }) => {
const $apollo = { queries: { clusterAgent: { loading } } };
wrapper = shallowMount(ClusterAgentShow, {
propsData,
mocks: { $apollo, clusterAgent },
stubs: { GlTab },
});
wrapper = extendedWrapper(
shallowMount(ClusterAgentShow, {
propsData,
mocks: { $apollo, clusterAgent },
slots,
stubs: { GlTab },
}),
);
};
const findCreatedText = () => wrapper.find('[data-testid="cluster-agent-create-info"]').text();
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
const findPaginationButtons = () => wrapper.find(GlKeysetPagination);
const findTokenCount = () => wrapper.find('[data-testid="cluster-agent-token-count"]').text();
const findCreatedText = () => wrapper.findByTestId('cluster-agent-create-info').text();
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findPaginationButtons = () => wrapper.findComponent(GlKeysetPagination);
const findTokenCount = () => wrapper.findByTestId('cluster-agent-token-count').text();
const findEESecurityTabSlot = () => wrapper.findByTestId('ee-security-tab');
afterEach(() => {
wrapper.destroy();
@ -87,7 +95,7 @@ describe('ClusterAgentShow', () => {
});
it('renders token table', () => {
expect(wrapper.find(TokenTable).exists()).toBe(true);
expect(wrapper.findComponent(TokenTable).exists()).toBe(true);
});
it('should not render pagination buttons when there are no additional pages', () => {
@ -188,8 +196,27 @@ describe('ClusterAgentShow', () => {
});
it('displays an alert message', () => {
expect(wrapper.find(GlAlert).exists()).toBe(true);
expect(wrapper.findComponent(GlAlert).exists()).toBe(true);
expect(wrapper.text()).toContain(ClusterAgentShow.i18n.loadingError);
});
});
describe('ee-security-tab slot', () => {
it('does not display when a slot is not passed in', async () => {
createWrapperWithoutApollo({ clusterAgent: defaultClusterAgent });
await nextTick();
expect(findEESecurityTabSlot().exists()).toBe(false);
});
it('does display when a slot is passed in', async () => {
createWrapperWithoutApollo({
clusterAgent: defaultClusterAgent,
slots: {
'ee-security-tab': `<gl-tab data-testid="ee-security-tab">Security Tab!</gl-tab>`,
},
});
await nextTick();
expect(findEESecurityTabSlot().exists()).toBe(true);
});
});
});

View File

@ -0,0 +1,66 @@
import { shallowMount } from '@vue/test-utils';
import { GlTab, GlTabs } from '@gitlab/ui';
import App from '~/google_cloud/components/app.vue';
import IncubationBanner from '~/google_cloud/components/incubation_banner.vue';
import ServiceAccounts from '~/google_cloud/components/service_accounts.vue';
describe('google_cloud App component', () => {
let wrapper;
const findIncubationBanner = () => wrapper.findComponent(IncubationBanner);
const findTabs = () => wrapper.findComponent(GlTabs);
const findTabItems = () => findTabs().findAllComponents(GlTab);
const findConfigurationTab = () => findTabItems().at(0);
const findDeploymentTab = () => findTabItems().at(1);
const findServicesTab = () => findTabItems().at(2);
const findServiceAccounts = () => findConfigurationTab().findComponent(ServiceAccounts);
beforeEach(() => {
const propsData = {
serviceAccounts: [{}, {}],
createServiceAccountUrl: '#url-create-service-account',
emptyIllustrationUrl: '#url-empty-illustration',
};
wrapper = shallowMount(App, { propsData });
});
afterEach(() => {
wrapper.destroy();
});
it('should contain incubation banner', () => {
expect(findIncubationBanner().exists()).toBe(true);
});
describe('google_cloud App tabs', () => {
it('should contain tabs', () => {
expect(findTabs().exists()).toBe(true);
});
it('should contain three tab items', () => {
expect(findTabItems().length).toBe(3);
});
describe('configuration tab', () => {
it('should exist', () => {
expect(findConfigurationTab().exists()).toBe(true);
});
it('should contain service accounts component', () => {
expect(findServiceAccounts().exists()).toBe(true);
});
});
describe('deployments tab', () => {
it('should exist', () => {
expect(findDeploymentTab().exists()).toBe(true);
});
});
describe('services tab', () => {
it('should exist', () => {
expect(findServicesTab().exists()).toBe(true);
});
});
});
});

View File

@ -0,0 +1,60 @@
import { mount } from '@vue/test-utils';
import { GlAlert, GlLink } from '@gitlab/ui';
import IncubationBanner from '~/google_cloud/components/incubation_banner.vue';
describe('IncubationBanner component', () => {
let wrapper;
const findAlert = () => wrapper.findComponent(GlAlert);
const findLinks = () => wrapper.findAllComponents(GlLink);
const findFeatureRequestLink = () => findLinks().at(0);
const findReportBugLink = () => findLinks().at(1);
const findShareFeedbackLink = () => findLinks().at(2);
beforeEach(() => {
const propsData = {
shareFeedbackUrl: 'url_general_feedback',
reportBugUrl: 'url_report_bug',
featureRequestUrl: 'url_feature_request',
};
wrapper = mount(IncubationBanner, { propsData });
});
afterEach(() => {
wrapper.destroy();
});
it('contains alert', () => {
expect(findAlert().exists()).toBe(true);
});
it('contains relevant text', () => {
expect(findAlert().text()).toContain(
'This is an experimental feature developed by GitLab Incubation Engineering.',
);
});
describe('has relevant gl-links', () => {
it('three in total', () => {
expect(findLinks().length).toBe(3);
});
it('contains feature request link', () => {
const link = findFeatureRequestLink();
expect(link.text()).toBe('request a feature');
expect(link.attributes('href')).toBe('url_feature_request');
});
it('contains report bug link', () => {
const link = findReportBugLink();
expect(link.text()).toBe('report a bug');
expect(link.attributes('href')).toBe('url_report_bug');
});
it('contains share feedback link', () => {
const link = findShareFeedbackLink();
expect(link.text()).toBe('share feedback');
expect(link.attributes('href')).toBe('url_general_feedback');
});
});
});

View File

@ -0,0 +1,79 @@
import { mount } from '@vue/test-utils';
import { GlButton, GlEmptyState, GlTable } from '@gitlab/ui';
import ServiceAccounts from '~/google_cloud/components/service_accounts.vue';
describe('ServiceAccounts component', () => {
describe('when the project does not have any service accounts', () => {
let wrapper;
const findEmptyState = () => wrapper.findComponent(GlEmptyState);
const findButtonInEmptyState = () => findEmptyState().findComponent(GlButton);
beforeEach(() => {
const propsData = {
list: [],
createUrl: '#create-url',
emptyIllustrationUrl: '#empty-illustration-url',
};
wrapper = mount(ServiceAccounts, { propsData });
});
afterEach(() => {
wrapper.destroy();
});
it('shows the empty state component', () => {
expect(findEmptyState().exists()).toBe(true);
});
it('shows the link to create new service accounts', () => {
const button = findButtonInEmptyState();
expect(button.exists()).toBe(true);
expect(button.text()).toBe('Create service account');
expect(button.attributes('href')).toBe('#create-url');
});
});
describe('when three service accounts are passed via props', () => {
let wrapper;
const findTitle = () => wrapper.find('h2');
const findDescription = () => wrapper.find('p');
const findTable = () => wrapper.findComponent(GlTable);
const findRows = () => findTable().findAll('tr');
const findButton = () => wrapper.findComponent(GlButton);
beforeEach(() => {
const propsData = {
list: [{}, {}, {}],
createUrl: '#create-url',
emptyIllustrationUrl: '#empty-illustration-url',
};
wrapper = mount(ServiceAccounts, { propsData });
});
it('shows the title', () => {
expect(findTitle().text()).toBe('Service Accounts');
});
it('shows the description', () => {
expect(findDescription().text()).toBe(
'Service Accounts keys authorize GitLab to deploy your Google Cloud project',
);
});
it('shows the table', () => {
expect(findTable().exists()).toBe(true);
});
it('table must have three rows + header row', () => {
expect(findRows().length).toBe(4);
});
it('shows the link to create new service accounts', () => {
const button = findButton();
expect(button.exists()).toBe(true);
expect(button.text()).toBe('Create service account');
expect(button.attributes('href')).toBe('#create-url');
});
});
});

View File

@ -27,6 +27,7 @@ exports[`VersionRow renders 1`] = `
>
<span
class="gl-truncate"
data-testid="truncate-end-container"
title="@gitlab-org/package-15"
>
<span

View File

@ -71,10 +71,10 @@ exports[`Project remove modal initialized matches the snapshot 1`] = `
</code>
</p>
<gl-form-textarea-stub
<gl-form-input-stub
id="confirm_name_input"
name="confirm_name_input"
noresize="true"
type="text"
/>
</div>

View File

@ -51,10 +51,10 @@ exports[`Project remove modal intialized matches the snapshot 1`] = `
</code>
</p>
<gl-form-textarea-stub
<gl-form-input-stub
id="confirm_name_input"
name="confirm_name_input"
noresize="true"
type="text"
/>
</div>

View File

@ -268,7 +268,7 @@ RSpec.describe ProjectsHelper do
end
end
describe '#link_to_set_password' do
describe '#no_password_message' do
let(:user) { create(:user, password_automatically_set: true) }
before do
@ -276,18 +276,18 @@ RSpec.describe ProjectsHelper do
end
context 'password authentication is enabled for Git' do
it 'returns link to set a password' do
it 'returns message prompting user to set password or set up a PAT' do
stub_application_setting(password_authentication_enabled_for_git?: true)
expect(helper.link_to_set_password).to match %r{<a href="#{edit_profile_password_path}">set a password</a>}
expect(helper.no_password_message).to eq('Your account is authenticated with SSO or SAML. To <a href="/help/gitlab-basics/start-using-git#pull-and-push" target="_blank" rel="noopener noreferrer">push and pull</a> over HTTP with Git using this account, you must <a href="/-/profile/password/edit">set a password</a> or <a href="/-/profile/personal_access_tokens">set up a Personal Access Token</a> to use instead of a password. For more information, see <a href="/help/gitlab-basics/start-using-git#clone-with-https" target="_blank" rel="noopener noreferrer">Clone with HTTPS</a>.')
end
end
context 'password authentication is disabled for Git' do
it 'returns link to create a personal access token' do
it 'returns message prompting user to set up a PAT' do
stub_application_setting(password_authentication_enabled_for_git?: false)
expect(helper.link_to_set_password).to match %r{<a href="#{profile_personal_access_tokens_path}">create a personal access token</a>}
expect(helper.no_password_message).to eq('Your account is authenticated with SSO or SAML. To <a href="/help/gitlab-basics/start-using-git#pull-and-push" target="_blank" rel="noopener noreferrer">push and pull</a> over HTTP with Git using this account, you must <a href="/-/profile/personal_access_tokens">set up a Personal Access Token</a> to use instead of a password. For more information, see <a href="/help/gitlab-basics/start-using-git#clone-with-https" target="_blank" rel="noopener noreferrer">Clone with HTTPS</a>.')
end
end
end
@ -987,8 +987,8 @@ RSpec.describe ProjectsHelper do
describe "#delete_confirm_phrase" do
subject { helper.delete_confirm_phrase(project) }
it 'includes the project full name' do
expect(subject).to eq("Delete #{project.full_name}")
it 'includes the project path with namespace' do
expect(subject).to eq(project.path_with_namespace)
end
end
end

View File

@ -1,35 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe BulkImports::Groups::Graphql::GetMilestonesQuery do
it 'has a valid query' do
tracker = create(:bulk_import_tracker)
context = BulkImports::Pipeline::Context.new(tracker)
query = GraphQL::Query.new(
GitlabSchema,
described_class.to_s,
variables: described_class.variables(context)
)
result = GitlabSchema.static_validator.validate(query)
expect(result[:errors]).to be_empty
end
describe '#data_path' do
it 'returns data path' do
expected = %w[data group milestones nodes]
expect(described_class.data_path).to eq(expected)
end
end
describe '#page_info_path' do
it 'returns pagination information path' do
expected = %w[data group milestones page_info]
expect(described_class.page_info_path).to eq(expected)
end
end
end

View File

@ -49,6 +49,36 @@ RSpec.describe Gitlab::BackgroundMigration::FixMergeRequestDiffCommitUsers do
end
end
describe '#process' do
it 'processes the merge requests of the project' do
project = create(:project, :repository)
commit = project.commit
mr = create(
:merge_request_with_diffs,
source_project: project,
target_project: project
)
diff = mr.merge_request_diffs.first
create(
:merge_request_diff_commit,
merge_request_diff: diff,
sha: commit.sha,
relative_order: 9000
)
migration.process(project)
updated = diff
.merge_request_diff_commits
.find_by(sha: commit.sha, relative_order: 9000)
expect(updated.commit_author_id).not_to be_nil
expect(updated.committer_id).not_to be_nil
end
end
describe '#update_commit' do
let(:project) { create(:project, :repository) }
let(:mr) do

View File

@ -379,6 +379,22 @@ RSpec.describe CommitStatus do
end
end
describe '.retried_ordered' do
subject { described_class.retried_ordered.to_a }
let!(:statuses) do
[create_status(name: 'aa', ref: 'bb', status: 'running', retried: true),
create_status(name: 'cc', ref: 'cc', status: 'pending', retried: true),
create_status(name: 'aa', ref: 'cc', status: 'success', retried: true),
create_status(name: 'cc', ref: 'bb', status: 'success'),
create_status(name: 'aa', ref: 'bb', status: 'success')]
end
it 'returns retried statuses in order' do
is_expected.to eq(statuses.values_at(2, 0, 1))
end
end
describe '.running_or_pending' do
subject { described_class.running_or_pending.order(:id) }

View File

@ -6,6 +6,7 @@ RSpec.describe User do
include ProjectForksHelper
include TermsHelper
include ExclusiveLeaseHelpers
include LdapHelpers
it_behaves_like 'having unique enum values'
@ -5808,7 +5809,7 @@ RSpec.describe User do
end
describe '#active_for_authentication?' do
subject { user.active_for_authentication? }
subject(:active_for_authentication?) { user.active_for_authentication? }
let(:user) { create(:user) }
@ -5818,6 +5819,14 @@ RSpec.describe User do
end
it { is_expected.to be false }
it 'does not check if LDAP is allowed' do
stub_ldap_setting(enabled: true)
expect(Gitlab::Auth::Ldap::Access).not_to receive(:allowed?)
active_for_authentication?
end
end
context 'when user is a ghost user' do
@ -5828,6 +5837,28 @@ RSpec.describe User do
it { is_expected.to be false }
end
context 'when user is ldap_blocked' do
before do
user.ldap_block
end
it 'rechecks if LDAP is allowed when LDAP is enabled' do
stub_ldap_setting(enabled: true)
expect(Gitlab::Auth::Ldap::Access).to receive(:allowed?)
active_for_authentication?
end
it 'does not check if LDAP is allowed when LDAP is not enabled' do
stub_ldap_setting(enabled: false)
expect(Gitlab::Auth::Ldap::Access).not_to receive(:allowed?)
active_for_authentication?
end
end
context 'based on user type' do
using RSpec::Parameterized::TableSyntax

View File

@ -904,20 +904,20 @@
stylelint-declaration-strict-value "1.7.7"
stylelint-scss "3.18.0"
"@gitlab/svgs@1.219.0":
version "1.219.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.219.0.tgz#82735876b98bd3a46f42b4a424b45086ed48e7ac"
integrity sha512-UOy0+6A6PTbjNHLFBc70ATYztsiQfWHPORgPGnzugYJz2F7ewMr4p6R8d9avFqMNtVB5mIHSnbrsr0pp0XVMGA==
"@gitlab/svgs@1.220.0":
version "1.220.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.220.0.tgz#188bdefe86cdbf8be1faa7a92dbac31c728066c7"
integrity sha512-9QRXQG6IrQoviU86g2Y4l19yE81UyEg/iMoGetMfUdQ64NW6unLN7uNbUaO1ws1J0p7uG0dKwR6ohD7tEUPLFA==
"@gitlab/tributejs@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8"
integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw==
"@gitlab/ui@32.31.0":
version "32.31.0"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-32.31.0.tgz#e379f79f0797c98d67e121739add8dec8281a5d4"
integrity sha512-a/03Jgh3TJx0W1lJjsYZiAKbRQHGvomrGhzDvBpxKve2FXrYdo4G6gbwlIKJGiooB5YmZ5OIWhgnhQ8FSy15Aw==
"@gitlab/ui@32.33.0":
version "32.33.0"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-32.33.0.tgz#387c0c0fc515a44b8d115a1da1903e84233fbaaf"
integrity sha512-wmyfRMEQ4ZQLCR4FS7fkCY1FCNX6amPyZYYzCZTV52NMtKlgaxczB7YkY1ufdtg5ctmI2NcQNkRGbdW3Et0Riw==
dependencies:
"@babel/standalone" "^7.0.0"
bootstrap-vue "2.20.1"