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
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue69
-rw-r--r--app/assets/javascripts/monitoring/stores/actions.js4
-rw-r--r--app/assets/javascripts/monitoring/stores/getters.js15
-rw-r--r--app/assets/javascripts/monitoring/stores/mutation_types.js2
-rw-r--r--app/assets/javascripts/monitoring/stores/mutations.js3
-rw-r--r--app/assets/javascripts/monitoring/stores/state.js1
-rw-r--r--app/assets/stylesheets/pages/experimental_separate_sign_up.scss33
-rw-r--r--app/assets/stylesheets/pages/prometheus.scss12
-rw-r--r--app/controllers/projects/environments_controller.rb1
-rw-r--r--app/helpers/auth_helper.rb12
-rw-r--r--app/models/user.rb5
-rw-r--r--app/services/metrics/dashboard/base_service.rb10
-rw-r--r--app/services/users/build_service.rb2
-rw-r--r--app/views/devise/shared/_experimental_separate_sign_up_flow_box.html.haml2
-rw-r--r--app/views/devise/shared/_experimental_separate_sign_up_flow_omniauth_box.haml13
-rw-r--r--app/views/layouts/devise_experimental_separate_sign_up_flow.html.haml4
-rw-r--r--changelogs/unreleased/197925-setting-minimum-password-length-breaks-sign-up-with-saml.yml5
-rw-r--r--changelogs/unreleased/reorder-signup-omniauth-options.yml5
-rw-r--r--lib/gitlab/auth/o_auth/auth_hash.rb2
-rw-r--r--locale/gitlab.pot6
-rw-r--r--spec/frontend/monitoring/components/dashboard_spec.js83
-rw-r--r--spec/frontend/monitoring/mock_data.js17
-rw-r--r--spec/frontend/monitoring/store/getters_spec.js55
-rw-r--r--spec/helpers/auth_helper_spec.rb9
-rw-r--r--spec/lib/gitlab/auth/ldap/user_spec.rb12
-rw-r--r--spec/lib/gitlab/auth/o_auth/user_spec.rb14
-rw-r--r--spec/lib/gitlab/auth/saml/user_spec.rb12
-rw-r--r--spec/models/user_spec.rb14
28 files changed, 370 insertions, 52 deletions
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index 2c51252be39..f6f119d4463 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -8,6 +8,7 @@ import {
GlDropdownItem,
GlFormGroup,
GlModal,
+ GlSearchBoxByType,
GlModalDirective,
GlTooltipDirective,
} from '@gitlab/ui';
@@ -15,6 +16,7 @@ import PanelType from 'ee_else_ce/monitoring/components/panel_type.vue';
import { s__ } from '~/locale';
import createFlash from '~/flash';
import Icon from '~/vue_shared/components/icon.vue';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { getParameterValues, mergeUrlParams, redirectTo } from '~/lib/utils/url_utility';
import invalidUrl from '~/lib/utils/invalid_url';
@@ -38,6 +40,7 @@ export default {
GlButton,
GlDropdown,
GlDropdownItem,
+ GlSearchBoxByType,
GlFormGroup,
GlModal,
@@ -52,6 +55,7 @@ export default {
GlTooltip: GlTooltipDirective,
TrackEvent: TrackEventDirective,
},
+ mixins: [glFeatureFlagsMixin()],
props: {
externalDashboardUrl: {
type: String,
@@ -198,13 +202,12 @@ export default {
'dashboard',
'emptyState',
'showEmptyState',
- 'environments',
'deploymentData',
'useDashboardEndpoint',
'allDashboards',
'additionalPanelTypesEnabled',
]),
- ...mapGetters('monitoringDashboard', ['getMetricStates']),
+ ...mapGetters('monitoringDashboard', ['getMetricStates', 'filteredEnvironments']),
firstDashboard() {
return this.environmentsEndpoint.length > 0 && this.allDashboards.length > 0
? this.allDashboards[0]
@@ -227,6 +230,9 @@ export default {
this.externalDashboardUrl.length
);
},
+ shouldRenderSearchableEnvironmentsDropdown() {
+ return this.glFeatures.searchableEnvironmentsDropdown;
+ },
},
created() {
this.setEndpoints({
@@ -255,6 +261,7 @@ export default {
'setGettingStartedEmptyState',
'setEndpoints',
'setPanelGroupMetrics',
+ 'setEnvironmentsSearchTerm',
]),
updatePanels(key, panels) {
this.setPanelGroupMetrics({
@@ -296,6 +303,9 @@ export default {
setFormValidity(isValid) {
this.formIsValid = isValid;
},
+ debouncedEnvironmentsSearch: _.debounce(function environmentsSearchOnInput(searchTerm) {
+ this.setEnvironmentsSearchTerm(searchTerm);
+ }, 500),
submitCustomMetricsForm() {
this.$refs.customMetricsForm.submit();
},
@@ -374,17 +384,36 @@ export default {
data-qa-selector="environments_dropdown"
class="mb-0 d-flex"
toggle-class="dropdown-menu-toggle"
+ menu-class="monitor-environment-dropdown-menu"
:text="currentEnvironmentName"
- :disabled="environments.length === 0"
+ :disabled="filteredEnvironments.length === 0"
>
- <gl-dropdown-item
- v-for="environment in environments"
- :key="environment.id"
- :active="environment.name === currentEnvironmentName"
- active-class="is-active"
- :href="environment.metrics_path"
- >{{ environment.name }}</gl-dropdown-item
- >
+ <div class="d-flex flex-column overflow-hidden">
+ <gl-search-box-by-type
+ v-if="shouldRenderSearchableEnvironmentsDropdown"
+ ref="monitorEnvironmentsDropdownSearch"
+ class="m-2"
+ @input="debouncedEnvironmentsSearch"
+ />
+ <div class="flex-fill overflow-auto">
+ <gl-dropdown-item
+ v-for="environment in filteredEnvironments"
+ :key="environment.id"
+ :active="environment.name === currentEnvironmentName"
+ active-class="is-active"
+ :href="environment.metrics_path"
+ >{{ environment.name }}</gl-dropdown-item
+ >
+ </div>
+ <div
+ v-if="shouldRenderSearchableEnvironmentsDropdown"
+ v-show="filteredEnvironments.length === 0"
+ ref="monitorEnvironmentsDropdownMsg"
+ class="text-secondary no-matches-message"
+ >
+ {{ s__('No matching results') }}
+ </div>
+ </div>
</gl-dropdown>
</gl-form-group>
@@ -415,18 +444,16 @@ export default {
variant="default"
class="mr-2 mt-1 js-rearrange-button"
@click="toggleRearrangingPanels"
+ >{{ __('Arrange charts') }}</gl-button
>
- {{ __('Arrange charts') }}
- </gl-button>
<gl-button
v-if="addingMetricsAvailable"
ref="addMetricBtn"
v-gl-modal="$options.addMetric.modalId"
variant="outline-success"
class="mr-2 mt-1"
+ >{{ $options.addMetric.title }}</gl-button
>
- {{ $options.addMetric.title }}
- </gl-button>
<gl-modal
v-if="addingMetricsAvailable"
ref="addMetricModal"
@@ -448,9 +475,8 @@ export default {
:disabled="!formIsValid"
variant="success"
@click="submitCustomMetricsForm"
+ >{{ __('Save changes') }}</gl-button
>
- {{ __('Save changes') }}
- </gl-button>
</div>
</gl-modal>
@@ -458,9 +484,8 @@ export default {
v-if="selectedDashboard.can_edit"
class="mt-1 js-edit-link"
:href="selectedDashboard.project_blob_path"
+ >{{ __('Edit dashboard') }}</gl-button
>
- {{ __('Edit dashboard') }}
- </gl-button>
<gl-button
v-if="externalDashboardUrl.length"
@@ -506,9 +531,9 @@ export default {
class="draggable-remove js-draggable-remove p-2 w-100 position-absolute d-flex justify-content-end"
@click="removePanel(groupData.key, groupData.panels, graphIndex)"
>
- <a class="mx-2 p-2 draggable-remove-link" :aria-label="__('Remove')"
- ><icon name="close"
- /></a>
+ <a class="mx-2 p-2 draggable-remove-link" :aria-label="__('Remove')">
+ <icon name="close" />
+ </a>
</div>
<panel-type
diff --git a/app/assets/javascripts/monitoring/stores/actions.js b/app/assets/javascripts/monitoring/stores/actions.js
index 61cd8621902..6303ed2b82f 100644
--- a/app/assets/javascripts/monitoring/stores/actions.js
+++ b/app/assets/javascripts/monitoring/stores/actions.js
@@ -30,6 +30,10 @@ export const setEndpoints = ({ commit }, endpoints) => {
commit(types.SET_ENDPOINTS, endpoints);
};
+export const setEnvironmentsSearchTerm = ({ commit }, searchTerm) => {
+ commit(types.SET_ENVIRONMENTS_SEARCH_TERM, searchTerm);
+};
+
export const setShowErrorBanner = ({ commit }, enabled) => {
commit(types.SET_SHOW_ERROR_BANNER, enabled);
};
diff --git a/app/assets/javascripts/monitoring/stores/getters.js b/app/assets/javascripts/monitoring/stores/getters.js
index a13157c6f87..ed1e3e3ffec 100644
--- a/app/assets/javascripts/monitoring/stores/getters.js
+++ b/app/assets/javascripts/monitoring/stores/getters.js
@@ -58,5 +58,20 @@ export const metricsWithData = state => groupKey => {
return res;
};
+/**
+ * Filter environments by names.
+ *
+ * This is used in the environments dropdown with searchable input.
+ * Also, this searchable dropdown is behind `searchable_environments_dropdown`
+ * feature flag
+ *
+ * @param {Object} state
+ * @returns {Array} List of environments
+ */
+export const filteredEnvironments = state =>
+ state.environments.filter(env =>
+ env.name.toLowerCase().includes((state.environmentsSearchTerm || '').trim().toLowerCase()),
+ );
+
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
diff --git a/app/assets/javascripts/monitoring/stores/mutation_types.js b/app/assets/javascripts/monitoring/stores/mutation_types.js
index 74068e1d846..73d402ac6df 100644
--- a/app/assets/javascripts/monitoring/stores/mutation_types.js
+++ b/app/assets/javascripts/monitoring/stores/mutation_types.js
@@ -21,3 +21,5 @@ export const SET_GETTING_STARTED_EMPTY_STATE = 'SET_GETTING_STARTED_EMPTY_STATE'
export const SET_NO_DATA_EMPTY_STATE = 'SET_NO_DATA_EMPTY_STATE';
export const SET_SHOW_ERROR_BANNER = 'SET_SHOW_ERROR_BANNER';
export const SET_PANEL_GROUP_METRICS = 'SET_PANEL_GROUP_METRICS';
+
+export const SET_ENVIRONMENTS_SEARCH_TERM = 'SET_ENVIRONMENTS_SEARCH_TERM';
diff --git a/app/assets/javascripts/monitoring/stores/mutations.js b/app/assets/javascripts/monitoring/stores/mutations.js
index 506a30ae619..e14425d7c6c 100644
--- a/app/assets/javascripts/monitoring/stores/mutations.js
+++ b/app/assets/javascripts/monitoring/stores/mutations.js
@@ -196,4 +196,7 @@ export default {
const panelGroup = state.dashboard.panel_groups.find(pg => payload.key === pg.key);
panelGroup.panels = payload.panels;
},
+ [types.SET_ENVIRONMENTS_SEARCH_TERM](state, searchTerm) {
+ state.environmentsSearchTerm = searchTerm;
+ },
};
diff --git a/app/assets/javascripts/monitoring/stores/state.js b/app/assets/javascripts/monitoring/stores/state.js
index ee8a85ea222..2c6758dfce2 100644
--- a/app/assets/javascripts/monitoring/stores/state.js
+++ b/app/assets/javascripts/monitoring/stores/state.js
@@ -15,6 +15,7 @@ export default () => ({
deploymentData: [],
environments: [],
+ environmentsSearchTerm: '',
allDashboards: [],
currentDashboard: null,
projectPath: null,
diff --git a/app/assets/stylesheets/pages/experimental_separate_sign_up.scss b/app/assets/stylesheets/pages/experimental_separate_sign_up.scss
index 5a80ea79600..aeeb8b7384d 100644
--- a/app/assets/stylesheets/pages/experimental_separate_sign_up.scss
+++ b/app/assets/stylesheets/pages/experimental_separate_sign_up.scss
@@ -12,6 +12,7 @@
max-width: 900px;
&.navless-container {
+ padding: 35px $gl-padding;
// overriding .devise-layout-html.navless-container to support the sticky footer
// without having a header on size xs
@include media-breakpoint-down(xs) {
@@ -24,6 +25,7 @@
.signup-heading h2 {
font-weight: $gl-font-weight-bold;
padding: 0 $gl-padding;
+ font-size: $gl-font-size-28;
@include media-breakpoint-down(md) {
font-size: $gl-font-size-large;
@@ -49,4 +51,35 @@
color: $red-700;
}
}
+
+ .omniauth-divider {
+ &::before,
+ &::after {
+ content: '';
+ flex: 1;
+ border-bottom: 1px solid $gray-dark;
+ margin: $gl-padding-24 0;
+ }
+
+ &::before {
+ margin-right: $gl-padding;
+ }
+
+ &::after {
+ margin-left: $gl-padding;
+ }
+ }
+
+ .omniauth-btn {
+ width: 48%;
+
+ @include media-breakpoint-down(md) {
+ width: 100%;
+ }
+
+ img {
+ width: $default-icon-size;
+ height: $default-icon-size;
+ }
+ }
}
diff --git a/app/assets/stylesheets/pages/prometheus.scss b/app/assets/stylesheets/pages/prometheus.scss
index e20e58e21cf..e759423f6e5 100644
--- a/app/assets/stylesheets/pages/prometheus.scss
+++ b/app/assets/stylesheets/pages/prometheus.scss
@@ -58,6 +58,18 @@
.custom-time-range-form-group > label {
padding-bottom: $gl-padding;
}
+
+ .monitor-environment-dropdown-menu {
+ &.show {
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+ }
+
+ .no-matches-message {
+ padding: $gl-padding-8 $gl-padding-12;
+ }
+ }
}
.prometheus-panel {
diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb
index 70c4b536854..b4b2bf01831 100644
--- a/app/controllers/projects/environments_controller.rb
+++ b/app/controllers/projects/environments_controller.rb
@@ -14,6 +14,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController
before_action :expire_etag_cache, only: [:index], unless: -> { request.format.json? }
before_action only: [:metrics, :additional_metrics, :metrics_dashboard] do
push_frontend_feature_flag(:prometheus_computed_alerts)
+ push_frontend_feature_flag(:searchable_environments_dropdown)
end
before_action do
push_frontend_feature_flag(:auto_stop_environments)
diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
index a9c4cfe7dcc..e8d3d5f62cb 100644
--- a/app/helpers/auth_helper.rb
+++ b/app/helpers/auth_helper.rb
@@ -89,7 +89,17 @@ module AuthHelper
def enabled_button_based_providers
disabled_providers = Gitlab::CurrentSettings.disabled_oauth_sign_in_sources || []
- button_based_providers.map(&:to_s) - disabled_providers
+ providers = button_based_providers.map(&:to_s) - disabled_providers
+ providers.sort_by do |provider|
+ case provider
+ when 'google_oauth2'
+ 0
+ when 'github'
+ 1
+ else
+ 2
+ end
+ end
end
def button_based_providers_enabled?
diff --git a/app/models/user.rb b/app/models/user.rb
index be9f528e1bd..e86c0a1826d 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -394,6 +394,11 @@ class User < ApplicationRecord
Gitlab::CurrentSettings.minimum_password_length..Devise.password_length.max
end
+ # Generate a random password that conforms to the current password length settings
+ def random_password
+ Devise.friendly_token(password_length.max)
+ end
+
# Devise method overridden to allow sign in with email or username
def find_for_database_authentication(warden_conditions)
conditions = warden_conditions.dup
diff --git a/app/services/metrics/dashboard/base_service.rb b/app/services/metrics/dashboard/base_service.rb
index c51c88d776a..40c015dff9c 100644
--- a/app/services/metrics/dashboard/base_service.rb
+++ b/app/services/metrics/dashboard/base_service.rb
@@ -38,13 +38,9 @@ module Metrics
# Determines whether users should be able to view
# dashboards at all.
def allowed?
- if params[:environment]
- Ability.allowed?(current_user, :read_environment, project)
- elsif params[:cluster]
- true # Authorization handled at controller level
- else
- false
- end
+ return false unless params[:environment]
+
+ Ability.allowed?(current_user, :read_environment, project)
end
# Returns a new dashboard Hash, supplemented with DB info
diff --git a/app/services/users/build_service.rb b/app/services/users/build_service.rb
index d18f20bc1db..56631bf2785 100644
--- a/app/services/users/build_service.rb
+++ b/app/services/users/build_service.rb
@@ -23,7 +23,7 @@ module Users
@reset_token = user.generate_reset_token if params[:reset_password]
if user_params[:force_random_password]
- random_password = Devise.friendly_token.first(User.password_length.min)
+ random_password = User.random_password
user.password = user.password_confirmation = random_password
end
end
diff --git a/app/views/devise/shared/_experimental_separate_sign_up_flow_box.html.haml b/app/views/devise/shared/_experimental_separate_sign_up_flow_box.html.haml
index 4832861445b..7de7dec61b0 100644
--- a/app/views/devise/shared/_experimental_separate_sign_up_flow_box.html.haml
+++ b/app/views/devise/shared/_experimental_separate_sign_up_flow_box.html.haml
@@ -41,3 +41,5 @@
= recaptcha_tags
.submit-container.mt-3
= f.submit _("Register"), class: "btn-register btn btn-block btn-success mb-0 p-2", data: { qa_selector: 'new_user_register_button' }
+ - if omniauth_enabled? && button_based_providers_enabled?
+ = render 'devise/shared/experimental_separate_sign_up_flow_omniauth_box'
diff --git a/app/views/devise/shared/_experimental_separate_sign_up_flow_omniauth_box.haml b/app/views/devise/shared/_experimental_separate_sign_up_flow_omniauth_box.haml
new file mode 100644
index 00000000000..d9143d90430
--- /dev/null
+++ b/app/views/devise/shared/_experimental_separate_sign_up_flow_omniauth_box.haml
@@ -0,0 +1,13 @@
+.omniauth-divider.d-flex.align-items-center.text-center
+ = _("or")
+%label.label-bold.d-block
+ = _("Create an account using:")
+- providers = enabled_button_based_providers
+.d-flex.justify-content-between.flex-wrap
+ - providers.each do |provider|
+ - has_icon = provider_has_icon?(provider)
+ = link_to omniauth_authorize_path(:user, provider), method: :post, class: "btn d-flex align-items-center omniauth-btn text-left oauth-login mb-2 p-2 #{qa_class_for_provider(provider)}", id: "oauth-login-#{provider}" do
+ - if has_icon
+ = provider_image_tag(provider)
+ %span.ml-2
+ = label_for_provider(provider)
diff --git a/app/views/layouts/devise_experimental_separate_sign_up_flow.html.haml b/app/views/layouts/devise_experimental_separate_sign_up_flow.html.haml
index 2f05717fc0e..3a5c5399355 100644
--- a/app/views/layouts/devise_experimental_separate_sign_up_flow.html.haml
+++ b/app/views/layouts/devise_experimental_separate_sign_up_flow.html.haml
@@ -9,10 +9,10 @@
= render "layouts/broadcast"
.content
= render "layouts/flash"
- .row.mb-3
+ .row.mb-6
.col-sm-8.offset-sm-2.col-md-6.offset-md-3.new-session-forms-container
= render_if_exists 'layouts/devise_help_text'
- .text-center.signup-heading.mt-3.mb-3
+ .text-center.signup-heading.mb-3
= image_tag(image_url('logo.svg'), class: 'gitlab-logo', alt: 'GitLab Logo')
- if content_for?(:page_title)
%h2= yield :page_title
diff --git a/changelogs/unreleased/197925-setting-minimum-password-length-breaks-sign-up-with-saml.yml b/changelogs/unreleased/197925-setting-minimum-password-length-breaks-sign-up-with-saml.yml
new file mode 100644
index 00000000000..0530fd88749
--- /dev/null
+++ b/changelogs/unreleased/197925-setting-minimum-password-length-breaks-sign-up-with-saml.yml
@@ -0,0 +1,5 @@
+---
+title: Fixes random passwords generated not conforming to minimum_password_length setting
+merge_request: 23387
+author:
+type: fixed
diff --git a/changelogs/unreleased/reorder-signup-omniauth-options.yml b/changelogs/unreleased/reorder-signup-omniauth-options.yml
new file mode 100644
index 00000000000..46f9a2dcdb6
--- /dev/null
+++ b/changelogs/unreleased/reorder-signup-omniauth-options.yml
@@ -0,0 +1,5 @@
+---
+title: Reorder signup omniauth options
+merge_request: 23082
+author:
+type: changed
diff --git a/lib/gitlab/auth/o_auth/auth_hash.rb b/lib/gitlab/auth/o_auth/auth_hash.rb
index 76f2827af1a..b37a9225dd7 100644
--- a/lib/gitlab/auth/o_auth/auth_hash.rb
+++ b/lib/gitlab/auth/o_auth/auth_hash.rb
@@ -34,7 +34,7 @@ module Gitlab
end
def password
- @password ||= Gitlab::Utils.force_utf8(Devise.friendly_token[0, 8].downcase)
+ @password ||= Gitlab::Utils.force_utf8(::User.random_password.downcase)
end
def location
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 1d3a7e2a958..aad7e54b9db 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -5361,6 +5361,9 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
+msgid "Create an account using:"
+msgstr ""
+
msgid "Create an issue"
msgstr ""
@@ -22721,6 +22724,9 @@ msgstr ""
msgid "opened %{timeAgo}"
msgstr ""
+msgid "or"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/spec/frontend/monitoring/components/dashboard_spec.js b/spec/frontend/monitoring/components/dashboard_spec.js
index 007429a3d02..195abae3783 100644
--- a/spec/frontend/monitoring/components/dashboard_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_spec.js
@@ -28,6 +28,15 @@ describe('Dashboard', () => {
let wrapper;
let mock;
+ const findEnvironmentsDropdown = () => wrapper.find({ ref: 'monitorEnvironmentsDropdown' });
+ const findAllEnvironmentsDropdownItems = () => findEnvironmentsDropdown().findAll(GlDropdownItem);
+ const setSearchTerm = searchTerm => {
+ wrapper.vm.$store.commit(
+ `monitoringDashboard/${types.SET_ENVIRONMENTS_SEARCH_TERM}`,
+ searchTerm,
+ );
+ };
+
const createShallowWrapper = (props = {}, options = {}) => {
wrapper = shallowMount(Dashboard, {
localVue,
@@ -52,9 +61,6 @@ describe('Dashboard', () => {
});
};
- const findEnvironmentsDropdown = () => wrapper.find({ ref: 'monitorEnvironmentsDropdown' });
- const findAllEnvironmentsDropdownItems = () => findEnvironmentsDropdown().findAll(GlDropdownItem);
-
beforeEach(() => {
store = createStore();
mock = new MockAdapter(axios);
@@ -155,12 +161,9 @@ describe('Dashboard', () => {
wrapper.vm
.$nextTick()
.then(() => {
- const environmentDropdownItems = findAllEnvironmentsDropdownItems();
+ expect(findAllEnvironmentsDropdownItems().length).toEqual(environmentData.length);
- expect(wrapper.vm.environments.length).toEqual(environmentData.length);
- expect(environmentDropdownItems.length).toEqual(wrapper.vm.environments.length);
-
- environmentDropdownItems.wrappers.forEach((itemWrapper, index) => {
+ findAllEnvironmentsDropdownItems().wrappers.forEach((itemWrapper, index) => {
const anchorEl = itemWrapper.find('a');
if (anchorEl.exists() && environmentData[index].metrics_path) {
const href = anchorEl.attributes('href');
@@ -248,6 +251,70 @@ describe('Dashboard', () => {
});
});
+ describe('searchable environments dropdown', () => {
+ beforeEach(() => {
+ createMountedWrapper(
+ { hasMetrics: true },
+ {
+ attachToDocument: true,
+ stubs: ['graph-group', 'panel-type'],
+ provide: {
+ glFeatures: { searchableEnvironmentsDropdown: true },
+ },
+ },
+ );
+
+ setupComponentStore(wrapper);
+
+ return wrapper.vm.$nextTick();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders a search input', () => {
+ expect(wrapper.find({ ref: 'monitorEnvironmentsDropdownSearch' }).exists()).toBe(true);
+ });
+
+ it('renders dropdown items', () => {
+ findAllEnvironmentsDropdownItems().wrappers.forEach((itemWrapper, index) => {
+ const anchorEl = itemWrapper.find('a');
+ if (anchorEl.exists()) {
+ expect(anchorEl.text()).toBe(environmentData[index].name);
+ }
+ });
+ });
+
+ it('filters rendered dropdown items', () => {
+ const searchTerm = 'production';
+ const resultEnvs = environmentData.filter(({ name }) => name.indexOf(searchTerm) !== -1);
+ setSearchTerm(searchTerm);
+
+ return wrapper.vm.$nextTick(() => {
+ expect(findAllEnvironmentsDropdownItems().length).toEqual(resultEnvs.length);
+ });
+ });
+
+ it('does not filter dropdown items if search term is empty string', () => {
+ const searchTerm = '';
+ setSearchTerm(searchTerm);
+
+ return wrapper.vm.$nextTick(() => {
+ expect(findAllEnvironmentsDropdownItems().length).toEqual(environmentData.length);
+ });
+ });
+
+ it("shows error message if search term doesn't match", () => {
+ const searchTerm = 'does-not-exist';
+ setSearchTerm(searchTerm);
+
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.find({ ref: 'monitorEnvironmentsDropdownMsg' }).isVisible()).toBe(true);
+ });
+ });
+ });
+
describe('drag and drop function', () => {
const findDraggables = () => wrapper.findAll(VueDraggable);
const findEnabledDraggables = () => findDraggables().filter(f => !f.attributes('disabled'));
diff --git a/spec/frontend/monitoring/mock_data.js b/spec/frontend/monitoring/mock_data.js
index 094554f525c..ada3e44f0a4 100644
--- a/spec/frontend/monitoring/mock_data.js
+++ b/spec/frontend/monitoring/mock_data.js
@@ -331,6 +331,14 @@ export const mockedQueryResultPayloadCoresTotal = {
],
};
+const extraEnvironmentData = new Array(15).fill(null).map((_, idx) => ({
+ id: 136 + idx,
+ name: `no-deployment/noop-branch-${idx}`,
+ state: 'available',
+ created_at: '2018-07-04T18:39:41.702Z',
+ updated_at: '2018-07-04T18:44:54.010Z',
+}));
+
export const environmentData = [
{
id: 34,
@@ -368,14 +376,7 @@ export const environmentData = [
id: 128,
},
},
- {
- id: 36,
- name: 'no-deployment/noop-branch',
- state: 'available',
- created_at: '2018-07-04T18:39:41.702Z',
- updated_at: '2018-07-04T18:44:54.010Z',
- },
-];
+].concat(extraEnvironmentData);
export const metricsDashboardResponse = {
dashboard: {
diff --git a/spec/frontend/monitoring/store/getters_spec.js b/spec/frontend/monitoring/store/getters_spec.js
index 097a5ca7f7c..263050b462f 100644
--- a/spec/frontend/monitoring/store/getters_spec.js
+++ b/spec/frontend/monitoring/store/getters_spec.js
@@ -3,6 +3,7 @@ import mutations from '~/monitoring/stores/mutations';
import * as types from '~/monitoring/stores/mutation_types';
import { metricStates } from '~/monitoring/constants';
import {
+ environmentData,
metricsDashboardPayload,
mockedEmptyResult,
mockedQueryResultPayload,
@@ -214,4 +215,58 @@ describe('Monitoring store Getters', () => {
});
});
});
+
+ describe('filteredEnvironments', () => {
+ let state;
+ const setupState = (initState = {}) => {
+ state = {
+ ...state,
+ ...initState,
+ };
+ };
+
+ beforeAll(() => {
+ setupState({
+ environments: environmentData,
+ });
+ });
+
+ afterAll(() => {
+ state = null;
+ });
+
+ [
+ {
+ input: '',
+ output: 17,
+ },
+ {
+ input: ' ',
+ output: 17,
+ },
+ {
+ input: null,
+ output: 17,
+ },
+ {
+ input: 'does-not-exist',
+ output: 0,
+ },
+ {
+ input: 'noop-branch-',
+ output: 15,
+ },
+ {
+ input: 'noop-branch-9',
+ output: 1,
+ },
+ ].forEach(({ input, output }) => {
+ it(`filteredEnvironments returns ${output} items for ${input}`, () => {
+ setupState({
+ environmentsSearchTerm: input,
+ });
+ expect(getters.filteredEnvironments(state).length).toBe(output);
+ });
+ });
+ });
});
diff --git a/spec/helpers/auth_helper_spec.rb b/spec/helpers/auth_helper_spec.rb
index cb7c670198d..9179019cd6a 100644
--- a/spec/helpers/auth_helper_spec.rb
+++ b/spec/helpers/auth_helper_spec.rb
@@ -73,12 +73,17 @@ describe AuthHelper do
describe 'enabled_button_based_providers' do
before do
- allow(helper).to receive(:auth_providers) { [:twitter, :github] }
+ allow(helper).to receive(:auth_providers) { [:twitter, :github, :google_oauth2] }
end
context 'all providers are enabled to sign in' do
it 'returns all the enabled providers from settings' do
- expect(helper.enabled_button_based_providers).to include('twitter', 'github')
+ expect(helper.enabled_button_based_providers).to include('twitter', 'github', 'google_oauth2')
+ end
+
+ it 'puts google and github in the beginning' do
+ expect(helper.enabled_button_based_providers.first).to eq('google_oauth2')
+ expect(helper.enabled_button_based_providers.second).to eq('github')
end
end
diff --git a/spec/lib/gitlab/auth/ldap/user_spec.rb b/spec/lib/gitlab/auth/ldap/user_spec.rb
index bc09de7b525..071d687b2bf 100644
--- a/spec/lib/gitlab/auth/ldap/user_spec.rb
+++ b/spec/lib/gitlab/auth/ldap/user_spec.rb
@@ -139,6 +139,18 @@ describe Gitlab::Auth::LDAP::User do
expect(gl_user).to be_confirmed
end
end
+
+ context 'when the current minimum password length is different from the default minimum password length' do
+ before do
+ stub_application_setting minimum_password_length: 21
+ end
+
+ it 'creates the user' do
+ ldap_user.save
+
+ expect(gl_user).to be_persisted
+ end
+ end
end
describe 'updating email' do
diff --git a/spec/lib/gitlab/auth/o_auth/user_spec.rb b/spec/lib/gitlab/auth/o_auth/user_spec.rb
index c621c0aa935..022a544395e 100644
--- a/spec/lib/gitlab/auth/o_auth/user_spec.rb
+++ b/spec/lib/gitlab/auth/o_auth/user_spec.rb
@@ -86,6 +86,20 @@ describe Gitlab::Auth::OAuth::User do
end
end
+ context 'when the current minimum password length is different from the default minimum password length' do
+ before do
+ stub_application_setting minimum_password_length: 21
+ end
+
+ it 'creates the user' do
+ stub_omniauth_config(allow_single_sign_on: [provider])
+
+ oauth_user.save
+
+ expect(gl_user).to be_persisted
+ end
+ end
+
it 'marks user as having password_automatically_set' do
stub_omniauth_config(allow_single_sign_on: [provider], external_providers: [provider])
diff --git a/spec/lib/gitlab/auth/saml/user_spec.rb b/spec/lib/gitlab/auth/saml/user_spec.rb
index 5546438b7ee..4c400636ddf 100644
--- a/spec/lib/gitlab/auth/saml/user_spec.rb
+++ b/spec/lib/gitlab/auth/saml/user_spec.rb
@@ -325,6 +325,18 @@ describe Gitlab::Auth::Saml::User do
expect(gl_user).to be_confirmed
end
end
+
+ context 'when the current minimum password length is different from the default minimum password length' do
+ before do
+ stub_application_setting minimum_password_length: 21
+ end
+
+ it 'creates the user' do
+ saml_user.save
+
+ expect(gl_user).to be_persisted
+ end
+ end
end
describe 'blocking' do
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 5620f211d9c..6f393d169a2 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -508,6 +508,20 @@ describe User, :do_not_mock_admin_mode do
end
end
+ describe '.random_password' do
+ let(:random_password) { described_class.random_password }
+
+ before do
+ expect(User).to receive(:password_length).and_return(88..128)
+ end
+
+ context 'length' do
+ it 'conforms to the current password length settings' do
+ expect(random_password.length).to eq(128)
+ end
+ end
+ end
+
describe '.password_length' do
let(:password_length) { described_class.password_length }